Unity容器中如何避免构造函数参数循环引用并有效解决?

2026-05-25 13:262阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计554个文字,预计阅读时间需要3分钟。

Unity容器中如何避免构造函数参数循环引用并有效解决?

关键词:Unity .NET5 .NET6 循环引用 循环依赖 Quartz StdSchedulerFactory 1、原因 在.NET6/NET5环境中,使用Unity替换默认容器,利用Quartz任务管理,发现注册ISchedulerFactory为StdSchedulerFactory后,出现循环引用问题。

关键字:

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

1、起因

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

System.StackOverflowException:“Exception_WasThrown”

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

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

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

2、重现 2.1、定义测试实体

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、定义接口及实现

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的时候不方便。

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

Unity容器中如何避免构造函数参数循环引用并有效解决?

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

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

本文共计554个文字,预计阅读时间需要3分钟。

Unity容器中如何避免构造函数参数循环引用并有效解决?

关键词:Unity .NET5 .NET6 循环引用 循环依赖 Quartz StdSchedulerFactory 1、原因 在.NET6/NET5环境中,使用Unity替换默认容器,利用Quartz任务管理,发现注册ISchedulerFactory为StdSchedulerFactory后,出现循环引用问题。

关键字:

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

1、起因

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

System.StackOverflowException:“Exception_WasThrown”

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

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

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

2、重现 2.1、定义测试实体

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、定义接口及实现

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的时候不方便。

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

Unity容器中如何避免构造函数参数循环引用并有效解决?

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

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