C# Unity Container Constructor Injection transient lifetime manager 同一实例服务

C# Unity Container Constructor Injection transient lifetime manager same instance served

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

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

这个例子简化了问题:

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 实例,并且列表中的所有记录都指向同一个实例
lkj 1
lkj 1

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

这里最好的方向是什么?我应该在什么地方寻找带有 Unity 的工厂模式?

假设您在每次调用 TestModel Get 时都希望 return 新模型(实质上是用某种 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;
    }
}