Resource Usage: IoC Containers And Large Object Graphs

In my about adding request/reply to the app controller, I talked about some resource usage problems that IoC containers can introduce if they are not used properly. Here’s that original text, again:

In a system that makes heavy use of an IoC container for automatic dependency injection, it is very easy for resource usage to get out of hand. For example, if an IoC container is used to instantiate a form and its presenter, and that presenter relies on 3 different interfaces that are implemented by other presenters with each of those presenters relying on an interface that is implemented by another form as well as other interfaces that are implemented by yet more presenters with views… the resource utilization of a system such as this quickly gets out of hand. In this example, there are a minimum of 4 forms that are instantiated and injected into presenters – and that only accounts for the second level of forms in the system. As the system becomes larger and the number of forms and other resource intensive objects being instantiated on start up can quickly get out of hand. This is especially dangerous in a limited resource platform, such as the Compact Framework for Windows Mobile devices – which is the context in which my team is currently using the application controller and these patterns.

I went on to talk about how the request/reply and command pattern implementations in my app controller would help to alleviate this problem by lazy loading the command and request handlers through an IoC container. All of this is still true, of course. I’m only repeating this because I felt that it was worth bringing to the foreground of it’s own post instead of hiding in the background of another subject matter.

In addition to the lazy loaded command and request handlers, though, there are other ways of making an IoC container behave and keep resource usage down to a minimum.

 

Autofac And Binding To A Func<T>

Joskha pointed out in the comments of the request/reply post that IoC containers like Autofac “can auto generate Func<T> dependencies given a registration of T.”  The idea is to register a Func<T> that returns the instance of the object or interface. As a pseudo-code example (not for any real IoC container, just to express the intent of the idea via code):

   1: public interface ISomething { }

   2:  

   3: public class SomeImplementation: ISomething { }

   4:  

   5: //pseudo-code for an IoC container registration

   6: RegisterWithFunc<ISomething>(() => {

   7:     return new SomeImplementation();

   8: });

This will have the same lazy-load effect that I talked about previously by injecting a proxy class into the ISomething dependency and calling the registered Func<T> from the proxy as soon as it is accessed by anything.  Joshka stated that Autofac can do this. I’m fairly sure Ninject can do this, too. I’m not sure about StructureMap, Unity, Spring.NET or any of the other .NET containers, though. Can someone else confirm the different containers?

For those containers that may not have this capability build in, though, it’s not terribly difficult to set this up manually.

 

Proxying A Single Method

This solution was originally posted in my complaint about C# anonymous types being crippled. Harry M suggested a workaround that uses a delegate in a generic proxy class that would let us sort-of have anonymous types in C#. The suggestion was a good one and I ended up using it not for anonymous types, but as a way to provide lazy-loading proxies to my IoC container’s registration.

Here’s the code that Harry posted in the comment:

   1: public class ActionClickListener: OnClickListener

   2: {

   3:    Action<View> _action;

   4:    

   5:    public ActionClickListener(Action<View> action)

   6:    {

   7:           _action = action

   8:    }

   9:    

  10:    public override void OnClick(View v)

  11:    {

  12:        _action(v);

  13:    }

  14: }

In this particular code example, the OnClickListener base class would provide an OnClick(Vew v) method definition, which is implemented by calling out to an Action<View> that we passed into the constructor. Mattmc3 then provided a usage example a few comments later:

   1: OnClickListener ocl = new ActionClickListener(

   2:     delegate(View v) {

   3:         // do whatever I want to here

   4:         // Console.WriteLine("delegate");

   5:     }

   6: );

We can use this code as a proxy class to lazy load our dependency in the same way the Func<T> functionality in Autofac works without actually needing that functionality baked into our IoC container. All we need is the ability to register a specific instance of an object against our interface or base class type. In this case, our pseudo-code registration would look like this:

   1: //pseudo-code for an IoC container registration

   2: RegisterInstance<OnClickListener>(ocl);

Here we are registering the ocl instance of the ActionClickListener as the type of object to return for the OnClickListener base class. When the OnClickListener is injected into an object that expects it and that object calls the .OnClick method of the OnClickListener base class, our proxy class (ActionClickListener) will call the code that was defined in the constructor’s Action<View> delegate. This, again, allows us to lazy load the the real dependencies at runtime.

 

Proxying A Complete Interface

You can easily combine the Action<T> of the previous example with a full interface proxy using the Func<T> idea from Autofac, as well:

   1: public interface IAnotherInterface

   2: {    

   3:     public void Execute();

   4:     public void SomethingElse();

   5: }

   6:  

   7: public class MyPresenter

   8: {

   9:     private IAnotherInterface _iDoSomethingSpecific;

  10:     public MyPresenter(IAnotherInterface iDoSomethingSpecific)

  11:     {

  12:         _iDoSomethingSpecific = iDoSomethingSpecific;

  13:     }

  14:     

  15:     public void DoWhatever()

  16:     {

  17:         _iDoSomethingSpecific.Execute();

  18:         _iDoSomethingSpecific.SomethingElse();

  19:     }    

  20: }

  21:  

  22: public class TheProxy: IAnotherInterface

  23: {

  24:     Func<IAnotherInterface> _lazyLoad;

  25:     IAnotherInterface _something;

  26:     

  27:     public SpecificCommandProxy(Func<IAnotherInterface> lazyLoad)

  28:     {

  29:         _lazyLoad = lazyLoad

  30:     }

  31:     

  32:     private IAnotherInterface EnsureSomething()

  33:     {

  34:         if (_something == null)

  35:         {

  36:             _something = _lazyLoad();

  37:         }

  38:     }

  39:     

  40:     public void Execute()

  41:     {

  42:         EnsureSomething();

  43:         return _something.Execute();

  44:     }

  45:     

  46:     public void SomethingElse()

  47:     {

  48:         EnsureSomething();

  49:         return _something.SomethingElse();

  50:     }

  51: }

  52:  

  53: public class ActualImplementation: IAnotherInterface

  54: {

  55:     public void Execute()

  56:     {

  57:         //do the real processing, here

  58:     }

  59:     

  60:     public void SomethingElse()

  61:     {

  62:         //more processing of the real stuff goes here

  63:     }

  64: }

  65:  

  66: //pseudo-code to register with a full proxy

  67: Register<IAnotherInterface>(new TheProxy(() => {return new ActualImplementation(); }));

This example provides a complete implementation of the Func<T> capabilities that Autofac has built into it and allows a full interface to be proxy’d rather than just a single method proxy like the example from Harry M.

 

Other Resource Management Solutions

I’m fairly sure that other IoC containers and general IoC container best practices will include other methods of managing resources. Perhaps your IoC container has an auto-proxy for lazy loading in a manner that is similar to NHibernate. Or StructureMap, for example, has the concept of type interceptors built in, which would easily allow you to build a lazy loading proxy.

What resource management techniques do you use with your IoC container(s)?


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in .NET, C#, Design Patterns, Principles and Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://realfiction.net Frank Quednau

    The current version of STructureMap will allow you to state a dependency on a Func. If it is known how to construct IFoo, the dependency will be passed happily into your consumer.

  • http://melioratingmonkey.blogspot.com/ MM

    According to David Hayden’s blog, Unity 2 has this feature too.
    http://www.davidhayden.me/2010/01/automatic-factories-in-unity-2-unity-2-tutorials-and-samples.html

  • http://melioratingmonkey.blogspot.com/ MM

    but… according to the link below, Unity cannot inject factories when the dependency has a constructor with parameters. seems pretty limiting. i know that autofac can handle this. don’t know about the others.

    http://www.machinaaurum.com.br/blog/post/Automatic-Factories-With-Unity-20.aspx

  • http://www.tavaresstudios.com Chris Tavares

    @MM: That’s not true. Well, not really.

    You can inject a Func from within Unity 2.0. However, the Func just turns around and calls container.Resolve. If the object that ends up being created has constructor parameters the container cannot infer, then you must configure the container appropriately to supply those parameters, just as if you had resolved the dependency directly.

    What you cannot do is create a factory that takes those extra parameters as arguments to the factory, it’s always just Func, not, for example, Func. We can look at expanding this in the next version, but I personally think going that route couples your code too strongly to the actual implementation, so I’ve been avoid doing that without a really good reason.

  • http://melioratingmonkey.blogspot.com/ MM

    @Chris Tavares

    Thanks for the response. I think being able to pass additional parameters to the factory is useful. It seems to me that the automatic factories should solve two problems. The first is that you can load “expensive” dependencies lazily. Obviously unity 2.0 solves that. But the other problem is that of not knowing exactly how to create something ahead of time. For example, reading some info from a file and creating objects based on the file contents. Being able to pass parameters to the factory method solves that type of problem too.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Chris / @MM

    turns out Ninject has the same basic thing as unity, then… you can register a Fun as a dependency, so the container provides itself to your func allowing you to lazy call context.Resolve. works really well. am using it in my current project now.

  • http://www.tavaresstudios.com Chris Tavares

    @MM

    I don’t deny it’s useful, I just don’t think that having the container create one on the fly is a good idea. There are too many ambiguities for my comfort level. If you want a factory that takes parameters, define an interface (could just be a func signature) for that factory and configure the container to inject an implementation of it explicitly.

  • http://melioratingmonkey.blogspot.com/ MM

    @Chris

    I think you’re right. I spent a little bit of time experimenting with this feature in autofac and after doing so, I think I’d be more comfortable doing exactly what you said.

  • http://msmvps.com/blogs/mako/ mako

    I use Windsor Container and it’s a very comfortable tool.
    The usage of the IoC might look like that
    ///

    /// Loader class are used for loading all dependencies between services in my project.
    ///

    public static class WindsorContainerLoader
    {
    #region Private fields

    private static readonly WindsorContainer Container;

    #endregion

    static WindsorContainerLoader()
    {
    Container = new WindsorContainer();
    Container.AddComponent(“EmailSender”, typeof(IEmailSender), typeof(EmailSender));

    }

    ///

    /// Returns object by component name.
    ///

    GetObjectByComponentName(string componentName)
    {
    return Container[componentName];
    }
    }

  • http://kozmic.pl Krzysztof Kozmic

    Castle Windsor has thing called TypedFactoryFacility, that works similarly to the delegate-based solution, but uses interface as a factory, instead of delegate which gives you more flexibility (generic methods, multiple methods, ability to release components).

    I also spiked a delegate-based solution. Perhaps it will be included in vNext of Windsor.

    I’m also thinking about adding transparent support for something you described in “Proxying A Complete Interface” section, but it’s in planning stages at the moment.

    On .NET 4 you can also use Lazy to explicitly make the dependency lazy.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Krzysztof

    oooh! i didn’t know about Lazy – that looks like something I can definitely use. :)

    i’d like to hear more about your transparent support for proxying. are you intending to use dyanmicproxy? … i’d really like to see a solution that doesn’t use that, so that we can take advantage of things in the compact framework.

  • http://scottwhite.blogspot.com Scott White

    You said Sprint.Net but I assume you mean’t Spring.Net?

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Scott White – oops! yes, thanks for noticing that. I fixed it. :)

  • http://melioratingmonkey.blogspot.com/ MM

    @derick

    But doesn’t using Func mean that your class now needs to know about Ninject? Isn’t the goal to keep as many classes as possible container agnostic?

  • Joshka

    In Autofac there’s no need to explicitly register a Func in the container, just T.

    public interface IDependency { }
    public class DependencyImplementation: IDependency { }
    public class SomeClass
    {
    private readonly Func _dependencyCreator;

    public SomeClass(Func dependencyCreator)
    {
    _dependencyCreator = dependencyCreator;
    }

    public void SomeMethodThatNeedsDependency()
    {
    var dependecy = _dependencyCreator();
    // …
    }
    }

    // …

    private static void UseSomeClass()
    {
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterType().As();
    var container = containerBuilder.Build();

    // later
    var someObject = container.Resolve();
    someObject.SomeMethodThatNeedsDependency();
    }

    To me this reads much better than the proposed alternatives.

  • Nick

    Autofac 2.0 also supports inferring Lazys out of the box.