Can any of existing IoC containers create the lazy

2019-02-15 08:47发布

问题:

I study different DI patterns. And now I interested in the lazy life-time implementation. For example, I want to write a proxy class that hides the factory behind a service's interface. Can any of existing IoC containers (.NET) create this kind of proxy class dynamically at runtime?

interface IService
{
    void Foo();
    void Bar();
}

class ServiceFactoryProxy : IService
{
    private readonly Func<IService> _factory;

    public ServiceFactoryProxy(Func<IService> factory)
    {
        if (factory == null) throw new ArgumentNullException("factory");
        _factory = factory;
    }

    public void Foo()
    {
        _factory().Foo();
    }

    public void Bar()
    {
        _factory().Foo();
    }
}

回答1:

Here is how it can be done in Castle:

http://litemedia.info/lazy-loading-property-with-castle-dynamicproxy2



回答2:

Unity does this out of the box. You declare a dependency of type Func<IService> in your constructor (like you did with ServiceFactoryProxy) and tell Unity how it should resolve IService. The container will generate the delegate for you.


Update

That proxy looks like an encapsulation of Lazy<T>.

If that is your intention you might want to have a look at this extension for Unity.

As far as I know Unity 3.0 will have support for .NET4 so I expect something similar to turn up as part of Unity with the next release.


Update2

It took me a while but I finished the lazy proxy feature. It generates IL code that looks like this

public class MyContract_LazyInstantiationProxy : IMyContract
{
  private readonly Lazy<IMyContract> instance;
  public MyContract_LazyInstantiationProxy(Func<IMyContract> factory)
  {
    Guard.AssertNotNull(factory, "factory");
    this.instance = new Lazy<IMyContract>(factory);
  }
  public IMyContract Instance
  {
    get { return this.instance.Value; }
  }
  public string Foo(Bar bar)
  {
    return this.Instance.Foo(bar);
  }
}

So you get the performance of hand-coded lazy proxies but they will be generated dynamically for you.

Have a look at the TecX project on codeplex. The lazy proxy generation can be found in the source code of TecX.Unity.Proxies. A sample on how to use it is in the according test project TecX.Unity.Proxies.Test.