是否可以将Unity配置为检测循环引用或拦截类型解析器以显示某些调试信息?
以下是一些依赖于彼此的接口和类
public interface IThing1 { }
public class Thing1 : IThing1
{
private IThing2 _thing2;
public Thing1(IThing2 thing2)
{
_thing2 = thing2;
}
}
public interface IThing2 { }
public class Thing2 : IThing2
{
private IThing1 _thing1;
public Thing2(IThing1 thing1)
{
_thing1 = thing1;
}
}
如果在Castle Windsor中配置了这两种类型,它将抛出异常并提供一些调试信息以查找循环引用:
Castle.MicroKernel.CircularDependencyException: Dependency cycle has been detected when trying to resolve component 'CircularIoC.Thing1'.
The resolution tree that resulted in the cycle is the following:
Component 'CircularIoC.Thing1' resolved as dependency of
component 'CircularIoC.Thing2' resolved as dependency of
component 'CircularIoC.Thing1' which is the root component being resolved.
如果Unity配置为解决这些类型
private static void ResolveWithUnity()
{
var container = new UnityContainer();
container.RegisterType<IThing1, Thing1>();
container.RegisterType<IThing2, Thing2>();
var thing = container.Resolve<IThing1>();
container.Dispose();
}
对container.Resolve&lt;&gt;的调用将导致StackOverflowException。
这是documented behaviour但是有一些更有用的信息会很好。是否有任何自定义可以提供有关循环引用的更多信息?
或者有没有办法挂钩到类型解析器进程来发出一些调试信息?我正在考虑装饰主类型解析器以输出正在解析的类型的名称。这将提供一些反馈和指向依赖项的指针,该指针导致循环引用。
虽然我知道改用不同的IoC可以解决问题,但不幸的是这不是一个选择。
答案 0 :(得分:1)
Unity遗憾地不支持这个(非常重要的)功能。 如果你愿意放弃它,你可以使用一些弯头油脂来实现智能装饰。
您需要的是覆盖所有注册方法,并为依赖项(dependency graph)构建和更新数据结构。 然后编写一个预先形成DFS以检测循环依赖关系的方法,您可以将其用作注册过程的终结器,如果可能存在循环依赖关系则将检测预解析,或者根据特定的解析使用它请求类型。
正如你所看到的,它有很多工作......
另一种选择,就是用装饰器包装解析方法并捕获 StackOverflowException ,分析它以确保它是由解析过程产生的,并构建一个适当的循环依赖异常。 / p>