Возможно ли, чтобы Unity ввел зависимый объект в родительский объект по требованию, а не когда инициализируется родительский объект?Unity Property setter injection по запросу
ответ
Да, имейте единство, вводящее Lazy<T>
вместо T
. Вот одна статья на эту тему: http://www.tomdupont.net/2012/07/lazy-unity-injection.html
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);
}
}
Спасибо! Также Unity 3.0 имеет эту функцию, уже встроенную в – Tommy