C#Unity容器构造函数注入瞬态生存期管理器提供了相同的实例



问题:我有一些XSD生成的复杂模型,我想让Unity来构建它们。类中有许多类的嵌套和数组,我不想更新它们。

如果我这样做并使用构造函数注入,那么每次使用生成类时似乎都不会得到新的模型。我的填充列表包含所有记录引用同一实例的记录。

这个例子简化了问题:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using Unity;
namespace sandbox
{
public class Test
{
private GetTestRec _getTestRec;
public Test(GetTestRec getTestRec)
{
_getTestRec = getTestRec;
}
public void RunMe()
{
var mylist = new List<TestModel>();
var InList = new List<StructIn>();
InList.Add(new StructIn() { Name = "asd", Amount = 5.55F });
InList.Add(new StructIn() { Name = "lkj", Amount = 1.00F });
foreach (var item in InList)
{
mylist.Add(_getTestRec.Get(item));
}
foreach (var item in mylist)
{
Console.WriteLine($"{item.Name} {item.Amount}" );
}
}
}
public class GetTestRec
{
private TestModel _testModel;
public GetTestRec(TestModel testModel)
{
//_testModel = testModel;
}
public TestModel Get(StructIn structIn)
{
_testModel = UnityConfig.Container.Resolve<TestModel>();
_testModel.Name = structIn.Name;
_testModel.Amount = structIn.Amount;
return _testModel;
}
}
public class TestModel
{
public TestModel()
{ }
public string Name { get; set; }
public float Amount { get; set; }
}
public struct StructIn
{
public string Name;
public float Amount;
}
}

在上面的代码中,TestModel被显式地解析。如果我解析GetTestRec并执行RunMe((。。。

var testThis = UnityConfig.Container.Resolve<Test>();
testThis.RunMe();

您可以看到它正确地生成了TestModel的两个实例,并将它们添加到列表
asd 5.55
lkj 1

但是,如果我注释掉显式解析,而是通过构造函数注入TestModel。。。

public class GetTestRec
{
private TestModel _testModel;
public GetTestRec(TestModel testModel)
{
_testModel = testModel;
}
public TestModel Get(StructIn structIn)
{
//_testModel = UnityConfig.Container.Resolve<TestModel>();
_testModel.Name = structIn.Name;
_testModel.Amount = structIn.Amount;
return _testModel;
}
}

您可以看到它只使用TestClass的一个实例,并且列表中的所有记录都指向同一个实例
lkj1
lkj1

如何使用构造函数注入并每次获得一个新实例?默认的瞬态生存期表示,它每次解析都会得到一个新实例,如果我调用resolve,那么我确实会获得一个新的实例。但是,使用构造函数时,我不认为会调用resolve,因为它以前已经被解析过了。

这里最好的方向是什么?我应该看看带有Unity的工厂模式吗?

假设您希望在每次调用TestModel Get时返回新模型(本质上是用某种DI友好代码替换new TestModel

根据需要使用对工厂方法的依赖关系(如Func<TestModel>(来创建它们。使用Unity,您不需要添加任何特殊的注册即可使其工作——它总是同时注册TFunc<T>(简称container => container.Resolve<T>()(。对于其他容器,您可能需要手动注册它,甚至创建工厂接口。

public class GetTestRec
{
private Func<TestModel> _testModelFactory;
public GetTestRec(Func<TestModel> testModelFactory)
{
_testModelFactory = testModelFactory;
}
public TestModel Get(StructIn structIn)
{
TestModel newModel = _testModelFactory();
newModel.Name = structIn.Name;
newModel.Amount = structIn.Amount;
return newModel;
}
}

最新更新