我正在尝试调试遗留代码库中的一些问题。我认为是由于抛出异常引起的,因为无法从Autofac容器中解析某些内容。但是,我认为异常被埋没在某个地方,我没有看到根本原因。我确信从控制器请求的东西要么找不到,要么可以找到的东西有一个无法满足的依赖。没有任何保护条款等,所以我认为我得到一个空参考问题。要尝试调试它,我想查看容器中找不到的所有请求。
是否有记录Autofac无法解决的所有请求?或者只是将所有请求记录到容器中?
答案 0 :(得分:34)
您可以通过注册一个特殊模块来为容器添加请求记录,该模块将捕获所有注册的Preparing
事件:
public class LogRequestsModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
// Use the event args to log detailed info
registration.Preparing += (sender, args) =>
Console.WriteLine(
"Resolving concrete type {0}",
args.Component.Activator.LimitType);
}
}
这是最简单的方法,可能会让你得到你想要的东西。在Preparing
事件记录信息后,您会看到异常弹出,您将知道哪个组件正在抛出。
如果您想获得更好的体验,可以在容器ChildLifetimeScopeBeginning
,ResolveOperationBeginning
,ResolveOperationEnding
和CurrentScopeEnding
事件上设置一些事件处理程序。
ChildLifetimeScopeBeginning
期间,您需要设置一些内容以自动附加到任何子生命周期ResolveOperationBeginning
事件。ResolveOperationBeginning
期间,您需要记录要解决的问题。ResolveOperationEnding
期间,您会记录任何异常情况。CurrentScopeEnding
期间,您需要取消订阅该范围内的任何事件,以便垃圾收集器可以清除其所有实例的生命周期范围。The Whitebox profiler project has a module实现了一些更高级的日志记录,但它没有针对最新的Autofac进行设置,因此您必须将其用作起点,而不是剪切/粘贴样本。
同样,最简单的解决方案是我上面发布的模块。
答案 1 :(得分:24)
只是建立Travis的优秀答案,以防将来帮助某人。
如果您的类结构非常深,如果您在合成层次结构中显示对象,则可能更容易发现有问题的路径。这可以通过以下方式完成:
using System;
using System.Text;
using Autofac;
using Autofac.Core;
namespace Tests
{
public class LogRequestModule : Module
{
public int depth = 0;
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
registration.Preparing += RegistrationOnPreparing;
registration.Activating += RegistrationOnActivating;
base.AttachToComponentRegistration(componentRegistry, registration);
}
private string GetPrefix()
{
return new string('-', depth * 2);
}
private void RegistrationOnPreparing(object sender, PreparingEventArgs preparingEventArgs)
{
Console.WriteLine("{0}Resolving {1}", GetPrefix(), preparingEventArgs.Component.Activator.LimitType);
depth++;
}
private void RegistrationOnActivating(object sender, ActivatingEventArgs<object> activatingEventArgs)
{
depth--;
Console.WriteLine("{0}Activating {1}", GetPrefix(), activatingEventArgs.Component.Activator.LimitType);
}
}
}
示例输出:
--Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapter
----Resolving SomeProject.Web.Integration.RestApiAdapter.Client.ClientFactory
------Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Resolving SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService
--------Resolving SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
--------Activating SomeProject.Web.Integration.RestApiAdapter.RestApiAdapterConfiguration
------Activating SomeProject.Web.Integration.RestApiAdapter.Client.Authentication.ApiClientAuthenticationService
答案 2 :(得分:3)
这个问题的其他答案适用于 Autofac 直到版本 5.x。任何为 Autofac 版本 6.x 寻找答案的人都应该查看 built in support for Diagnostics & Logging。 Autofac 不再需要自定义逻辑来实现此问题中请求的日志类型。
相关部分是:
DefaultDiagnosticTracer
来协调您的诊断。这是 Autofac 的一流部分。您进行设置,然后让您的容器订阅它。这是一个简单的示例,它仅使用 Console.WriteLine
来记录诊断内容。您应该将其替换为您希望用于您的应用的任何日志记录机制。
var tracer = new DefaultDiagnosticTracer();
tracer.OperationCompleted += (sender, args) =>
{
Console.WriteLine(args.TraceContent);
};
container.SubscribeToDiagnostics(tracer);