使用哪个生命周期管理器使用 Unity 在 foreach 循环中创建新实例
Which lifetime manager to use to create new instances in foreach loops using Unity
我有一个例子,我想在 foreach 循环中使用 DI 创建 class 的实例,但无法确定要使用哪个生命周期管理器。默认的生命周期管理器显然只会使用注入到控制器中的实例,我想在每次调用实例时创建新实例,如下例所示。我正在使用 Microsoft Unity
简单的界面class
public interface ISomeClass
{
string GetValue(string value);
}
public class SomeClass : ISomeClass
{
public string GetValue(string value)
{
return value;
}
}
在容器中注册
container.RegisterType<ISomeClass, SomeClass>(new TransientLifetimeManager());
实施
private readonly SomeClass _someClass;
public MyController(SomeClass someClass)
{
_someClass = someClass;
}
// someStringList would contain values like "hello", "world", "o", "hai"
public void Whatever(List<string> someStringList)
{
List<string> otherStringList = new List<string>();
foreach (var someString in someStringList)
{
// _someClass.GetValue will simply return the same value
otherStringList.Add(_someClass.GetValue(someString));
}
// otherStringList contain as many elements as the someStringList
// but all will be the same as the last element in the list
}
TransientLifetimeManager
生命周期管理器是必经之路。每次您或容器本身调用 Resolve
.
时,该对象都会创建新对象
所以重点是在 foreach
中以某种方式启动 Resolve
。 naive\simple 方法可能是将 IUnityContainer
本身注入到您的控制器中,IUnitContainer
本身始终可用...
private readonly IUnityContainer _container;
public MyController(IUnityContainer container)
{
_container = container;
}
然后手动解析 ISomeClass
:
foreach (var someString in someStringList)
{
var someClass = _container.Resolve<ISomeClass>();
otherStringList.Add(_someClass.GetValue(someString));
}
一般来说,我更喜欢某种工厂或原型模式,而不是注入 IUnityContainer
本身,因为这可能被认为是一种不好的做法。容器应该更多地用作隐形帮手而不是第一个class公民...
简单工厂方法可以是注册简单工厂方法:
_container.RegisterType<Func<ISomeClass>>(new InjectionFactory(_ =>
new Func<ISomeClass> (() => _container.Resolve<ISomeClass>())));
然后你可以将它注入你的控制器:
private readonly Func<ISomeClass> _factory;
public MyController(Func<ISomeClass> factory)
{
_factory = factory;
}
然后你把它当作:
foreach (var someString in someStringList)
{
ISomeClass someClass = _factory();
otherStringList.Add(_someClass.GetValue(someString));
}
第二种方法的好处是你有显式依赖而不是注入 IoC,这让你的设计更简洁。
我有一个例子,我想在 foreach 循环中使用 DI 创建 class 的实例,但无法确定要使用哪个生命周期管理器。默认的生命周期管理器显然只会使用注入到控制器中的实例,我想在每次调用实例时创建新实例,如下例所示。我正在使用 Microsoft Unity
简单的界面class
public interface ISomeClass
{
string GetValue(string value);
}
public class SomeClass : ISomeClass
{
public string GetValue(string value)
{
return value;
}
}
在容器中注册
container.RegisterType<ISomeClass, SomeClass>(new TransientLifetimeManager());
实施
private readonly SomeClass _someClass;
public MyController(SomeClass someClass)
{
_someClass = someClass;
}
// someStringList would contain values like "hello", "world", "o", "hai"
public void Whatever(List<string> someStringList)
{
List<string> otherStringList = new List<string>();
foreach (var someString in someStringList)
{
// _someClass.GetValue will simply return the same value
otherStringList.Add(_someClass.GetValue(someString));
}
// otherStringList contain as many elements as the someStringList
// but all will be the same as the last element in the list
}
TransientLifetimeManager
生命周期管理器是必经之路。每次您或容器本身调用 Resolve
.
所以重点是在 foreach
中以某种方式启动 Resolve
。 naive\simple 方法可能是将 IUnityContainer
本身注入到您的控制器中,IUnitContainer
本身始终可用...
private readonly IUnityContainer _container;
public MyController(IUnityContainer container)
{
_container = container;
}
然后手动解析 ISomeClass
:
foreach (var someString in someStringList)
{
var someClass = _container.Resolve<ISomeClass>();
otherStringList.Add(_someClass.GetValue(someString));
}
一般来说,我更喜欢某种工厂或原型模式,而不是注入 IUnityContainer
本身,因为这可能被认为是一种不好的做法。容器应该更多地用作隐形帮手而不是第一个class公民...
简单工厂方法可以是注册简单工厂方法:
_container.RegisterType<Func<ISomeClass>>(new InjectionFactory(_ =>
new Func<ISomeClass> (() => _container.Resolve<ISomeClass>())));
然后你可以将它注入你的控制器:
private readonly Func<ISomeClass> _factory;
public MyController(Func<ISomeClass> factory)
{
_factory = factory;
}
然后你把它当作:
foreach (var someString in someStringList)
{
ISomeClass someClass = _factory();
otherStringList.Add(_someClass.GetValue(someString));
}
第二种方法的好处是你有显式依赖而不是注入 IoC,这让你的设计更简洁。