• Unity容器构造函数参数循环引用问题及解决


    关键字:

    Unity .NET5 .NET6 循环引用 循环依赖 Quartz StdSchedulerFactory

    1、起因

    在.NET6/.NET5环境中,使用Unity替换默认容器,用到了Quartz任务管理,发现在注册ISchedulerFactory为StdSchedulerFactory后,获取ISchedulerFactory会报错:

    System.StackOverflowException:“Exception_WasThrown”

    根据报错推测是产生了循环引用,导致堆栈溢出;

    进一步尝试发现不用Unity用默认容器,没有这个问题;

    直接看解决方法,到文章末尾。

    2、重现

    2.1、定义测试实体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class TestModel
    {
        public string Code { get; set; }
     
        public string Name { get; set; }
     
        public TestModel()
        {
        }
     
        //引用自己的构造函数; 注意这里
        public TestModel(TestModel model)
        {
            this.Code = model.Code;
            this.Name = model.Name;
        }
    }

    2.2、定义接口及实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public interface ITest
    {
        string Hello(string name);
    }
     
    public class TestImpl : ITest
    {
        public TestImpl()
        {
        }
              
        //注意这个带参构造函数
        public TestImpl(TestModel model)
        {
        }
     
        public string Hello(string name)
        {
            return $"Hello, {name}";
        }
    }

    2.3、应用

    注册及获取ITest

    2.4、默认容器运行正常

    2.5、引用Unity容器,再次运行,报错

    程序除了把默认IoC容器改为Unity,其他没变化。如图报异常时容器为Unity。

    3、解决

    这是个很“奇怪”的问题,接口实现类TestImpl,因为有一个“没用到”的构造函数,其参数TestModel有一个“没用到”的构造函数,引用自身;会导致Unity容器获取该接口时报错。

    看“起因”Quartz的接口实现StdSchedulerFactory其中一个构造函数,参数类型NameValueCollection有引用自身的构造函数。

    解决办法:删除示例接口实现中的带参构造函数,或者参数类型不要有循环引用自己的构造函数都可以;但在涉及三方dll的时候不方便。

     

    更好的办法:对循环引用的参数类型做下注册。

    1
    2
    3
    4
    5
    6
    7
    8
    public void ConfigureServices(IServiceCollection services)
    {
        //添加循环引用参数类型TestModel的注册
        services.AddTransient(typeof(TestModel), _ => new TestModel());
     
        //注册ITest
        services.AddScoped<ITest, TestImpl>();
    }

    添加注册之后,运行正常。

  • 相关阅读:
    没有十几年的积累,你还真写不出什么好的代码
    NPDP考试应该怎么准备?考试攻略解析!
    【LeetCode】541. 反转字符串 II
    更换掉mac自带PHP,并配置Apache
    【C语言】指针传参引发的相关问题
    LeetCode 每日一题 2023/9/4-2023/9/10
    学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计 汉语言文学设计题材网页
    十四天算法快速入门第九天之「广度优先搜索 / 深度优先搜索」
    ARM hint instruction-WFI(Wait For Interrupt)指令详解
    Virtualenvwrapper 的安装教程
  • 原文地址:https://www.cnblogs.com/juntor/p/unity-stackoverflow-circular-reference.html