2013-08-22 2 views

ответ

0

Lazy<T> действительно не помогает, если вам действительно нужно «По требованию». Lazy<T> действительно работает только в том случае, если вам требуется отсроченное разрешение. Но затем, после первоначального решения, его нормально иметь такую ​​же ссылку.

Я решил это с помощью Castle.DynamicProxy. Мне нужно было ввести определенные зависимости «По требованию», то есть их нужно было разрешить во время использования (новое решение каждый раз), а не при создании «Depender».

Для этого я настроить мой контейнер таким образом: «по запросу»

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))); 
} 

Идея заключается в том, что я обеспечиваю метод для получения экземпляра Лямбда вызывается всякий раз, когда используется какой-либо из методов экземпляра. Объект 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); 
    } 
}