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

关键字:

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

起因

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

System.*Exception:“Exception_WasThrown”

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

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

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

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

重现

定义测试实体

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

定义接口及实现

public interface ITest
{
string Hello(string name);
} public class TestImpl : ITest
{
public TestImpl()
{
} //用unity容器时,model定义成循环引用了,会报错
public TestImpl(TestModel model)
{
} public string Hello(string name)
{
return $"Hello, {name}";
}
}

应用

注册及获取ITest

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

默认容器运行正常

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

引用unity容器:略

再次运行,报错

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

解决

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

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

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

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

解决办法:删除接口实现中的带参构造函数或自身引用的构造函数都可以;但在涉及三方dll的时候不方便。

更好的办法:对自身引用的参数做下注册。

public void ConfigureServices(IServiceCollection services)
{
//添加TestModel注册
services.AddTransient(typeof(TestModel), _ => new TestModel()); //注册ITest
services.AddScoped<ITest, TestImpl>();
}

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

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

上一篇:基于vite2+electron12后台管理模板|Electron后台框架系统


下一篇:linux安装python