使用哪个生命周期管理器使用 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,这让你的设计更简洁。