【问题标题】:C# Unity Container Constructor Injection transient lifetime manager same instance servedC# Unity Container Constructor Injection 瞬态生命周期管理器提供相同的实例
【发布时间】:2020-11-11 02:35:49
【问题描述】:

问题:我有一些复杂的 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
路基 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
路基 1

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

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

【问题讨论】:

    标签: c# instance unity-container resolve transient


    【解决方案1】:

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

    依赖工厂方法(如Func&lt;TestModel&gt;)根据需要创建它们。使用 Unity,您无需添加任何特殊注册即可使其正常工作 - 它始终同时注册 TFunc&lt;T&gt;(即简单的 container =&gt; container.Resolve&lt;T&gt;())。对于其他容器,您可能需要手动注册它甚至创建工厂接口。

    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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 2017-03-03
      • 2019-01-22
      相关资源
      最近更新 更多