Unity Property setter按需注入

时间:2013-08-22 10:16:24

标签: c# .net inversion-of-control unity-container

是否可以根据需要将Unity注入依赖对象转换为父对象,而不是在初始化父对象时?

2 个答案:

答案 0 :(得分:1)

是的,让Unity注入Lazy<T>而不是T。这是关于该主题的一篇文章:http://www.tomdupont.net/2012/07/lazy-unity-injection.html

答案 1 :(得分:0)

如果你确实需要&#34;随需应变,那么

Lazy<T>并没有什么帮助。&#34; Lazy<T>实际上只有在需要延迟解析时才有效。但是在最初的解决之后,它可以有相同的参考。

我通过使用Castle.DynamicProxy解决了这个问题。我需要注入某些依赖关系&#34; On Demand&#34;这意味着他们需要在使用时得到解决(每次都有新的决心),而不是在&#34; Depender&#34;积累。

为此,我按如下方式配置容器:

 private void UnityRegister(IUnityContainer container)
 {
    container.RegisterType<HttpContextBase>(new OnDemandInjectionFactory<HttpContextBase>(c => new HttpContextWrapper(HttpContext.Current)));
    container.RegisterType<HttpRequestBase>(new OnDemandInjectionFactory<HttpRequestBase>(c => new HttpRequestWrapper(HttpContext.Current.Request)));
    container.RegisterType<HttpSessionStateBase>(new OnDemandInjectionFactory<HttpSessionStateBase>(c => new HttpSessionStateWrapper(HttpContext.Current.Session)));
    container.RegisterType<HttpServerUtilityBase>(new OnDemandInjectionFactory<HttpServerUtilityBase>(c => new HttpServerUtilityWrapper(HttpContext.Current.Server)));
 }

我的想法是提供一种方法来按需检索实例。&#34;只要使用实例的任何方法,就会调用lambda。 Dependent对象实际上是对代理对象的引用,而不是对象本身。

<强> OnDemandInjectionFactory:

internal class OnDemandInjectionFactory<T> : InjectionFactory
{
    public OnDemandInjectionFactory(Func<IUnityContainer, T> proxiedObjectFactory) : base((container, type, name) => FactoryFunction(container, type, name, proxiedObjectFactory))
    {
    }

    private static object FactoryFunction(IUnityContainer container, Type type, string name, Func<IUnityContainer, T> proxiedObjectFactory)
    {
        var interceptor = new OnDemandInterceptor<T>(container, proxiedObjectFactory);
        var proxyGenerator = new ProxyGenerator();
        var proxy = proxyGenerator.CreateClassProxy(type, interceptor);
        return proxy;
    }
}

<强> OnDemandInterceptor:

internal class OnDemandInterceptor<T> : IInterceptor
{
    private readonly Func<IUnityContainer, T> _proxiedInstanceFactory;
    private readonly IUnityContainer _container;

    public OnDemandInterceptor(IUnityContainer container, Func<IUnityContainer, T> proxiedInstanceFactory)
    {
        _proxiedInstanceFactory = proxiedInstanceFactory;
        _container = container;
    }

    public void Intercept(IInvocation invocation)
    {
        var proxiedInstance = _proxiedInstanceFactory.Invoke(_container);

        var types = invocation.Arguments.Select(arg => arg.GetType()).ToArray();

        var method = typeof(T).GetMethod(invocation.Method.Name, types);

        invocation.ReturnValue = method.Invoke(proxiedInstance, invocation.Arguments);
    }
}