在这个问题 中:IoC 容器示例
有一个答案警告构造函数中抛出的异常很难调试/处理,因为 IoC 会吃掉它们。随后有评论说这不再是真的。
.Net IoCs 如何在今天减轻这个缺陷,或者还有一些仍然在这里受到影响?
我对至少有 2 个组织(基本上不仅仅是你的作者)使用的任何 .Net IoC 感兴趣,但如果你需要一个列表:Windsor、StructureMap、Autofac、Ninject。
在这个问题 中:IoC 容器示例
有一个答案警告构造函数中抛出的异常很难调试/处理,因为 IoC 会吃掉它们。随后有评论说这不再是真的。
.Net IoCs 如何在今天减轻这个缺陷,或者还有一些仍然在这里受到影响?
我对至少有 2 个组织(基本上不仅仅是你的作者)使用的任何 .Net IoC 感兴趣,但如果你需要一个列表:Windsor、StructureMap、Autofac、Ninject。
显然,这取决于您使用的 IoC 容器。根据我的经验,很少会“吞下”异常,它们是在解决时报告的。如果您遵循一个常见的最佳实践,即除了接受和验证构造函数中的依赖项之外不做任何事情,那么您应该没问题。
这是一个统一的例子:
void Main()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IAnimal, Dog>();
// Exception thrown on this line
var x = container.Resolve<IAnimal>();
}
public interface IAnimal
{
}
public class Dog : IAnimal
{
public Dog()
{
throw new Exception();
}
}
报告这个(我认为这是非常有用的):
ResolutionFailedException: Resolution of the dependency failed, type = "UserQuery+IAnimal", name = "(none)".
Exception occurred while: Calling constructor UserQuery+Dog().
Exception is: Exception - Exception of type 'System.Exception' was thrown.
-----------------------------------------------
At the time of the exception, the container was:
Resolving UserQuery+Dog,(none) (mapped from UserQuery+IAnimal, (none))
Calling constructor UserQuery+Dog()
我知道如果 StructureMap 在构造函数中出现异常,它们会冒泡,但是这个规则可能会有一些奇怪的细微差别。例如,如果您正在使用 SingletonPattern 调度程序,并且您分配的 Singleton 在程序执行的早期已经安静地崩溃了,StructureMap 会很高兴地将崩溃的实例输入到任何请求单例类型的东西中。那时很难说会发生什么,这完全取决于您的程序将如何处理对崩溃实例的访问。
但是,作为它会向您抛出的一个示例,如果您尝试使用无效或类型不匹配的参数调用对象的构造函数,它将在调用调用时抛出描述性错误。该设置通常可以正常工作,但您可以使用基本单元测试 (NUnit) 提前进行测试:
[Test]
public void Assert_registry_is_valid()
{
ObjectFactory.AssertConfigurationIsValid();
}
我当然从来没有遇到过 StructureMap 吞咽错误的问题。通常很容易从中获得有用的信息和完整的堆栈跟踪。
我知道 Autofac 会在尝试急切地解决依赖关系时“包装”抛出异常。AutofacException 的 InnerException 将是构造函数向容器抛出的异常。因此,您通常通过捕获 AutofacExceptions 并深入研究 InnerExceptions 来处理解析异常。
大多数 IoC 都有类似“TryResolve”的方法,可以优雅地返回 true 或 false 布尔值,如果解析成功,则输出参数会被初始化。这些方法是“吃掉”异常的方法,因此如果异常对您有用,请不要使用它们。几乎任何对基本 GetInstance 或 Resolve 方法的调用都会尝试生成水合的构造函数注入对象,这将抛出所选构造函数中发生的任何异常。