如何将所有解析请求记录到Autofac容器?

Gra*_*ler 24 logging dependency-injection autofac

我试图在遗留代码库中调试一些问题.我认为是由于抛出异常引起的,因为无法从Autofac容器中解析某些内容.但是我觉得异常被埋没在某个地方,我没有看到根本原因.我确信从控制器请求的东西要么找不到,要么可以找到的东西有一个无法满足的依赖.没有任何保护条款等,所以我认为我得到一个空参考问题.为了尝试调试这个,我希望看到容器中找不到的所有请求.

无论如何都要记录Autofac无法解决的所有请求?或者只是将所有请求记录到容器中?

Tra*_*lig 36

您可以通过注册一个特殊模块来为容器添加请求记录,该模块将捕获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);
  }
}
Run Code Online (Sandbox Code Playgroud)

这是最简单的方法,可能会让你得到你想要的.在Preparing事件记录信息之后,您将看到弹出的异常,您将知道正在抛出的组件.

如果你想更大胆的尝试,你可以在容器设置一些事件处理程序ChildLifetimeScopeBeginning,ResolveOperationBeginning,ResolveOperationEnding,和CurrentScopeEnding事件.

  • ChildLifetimeScopeBeginning您需要设置某些内容以自动附加到任何子生命周期ResolveOperationBeginning事件时.
  • ResolveOperationBeginning您记录要解决的内容期间.
  • ResolveOperationEnding您记录任何异常情况时.
  • CurrentScopeEnding您需要取消订阅该范围内的任何事件时,垃圾收集器可以清除其所有实例的生命周期范围.

Whitebox分析器项目有一个模块可以实现一些更高级的日志记录,但它没有针对最新的Autofac进行设置,因此您必须将其用作起点,而不是剪切/粘贴样本.

同样,最简单的解决方案是我上面发布的模块.

  • 我知道谢谢你们.但是,我非常感谢您为支持Autofac问题付出的努力.答案总是非常详细 (6认同)

Seb*_*n K 27

只是为了建立一个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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

样本输出:

--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
Run Code Online (Sandbox Code Playgroud)


Cra*_*ler 6

这个问题的其他答案适用于 Autofac 5.x 版本任何为Autofac 版本 6.x寻找答案的人都应该查看对 Diagnostics & Logging 的内置支持。Autofac 不再需要自定义逻辑来实现此问题中请求的日志记录类型。

其中的相关部分是:

  • 您不再需要将其集成到您的注册级逻辑中。如果您愿意的话也可以,但链接 URL 中有一个示例
  • 使用 aDefaultDiagnosticTracer来协调您的诊断。这是 Autofac 的一流部分。您设置它,然后让您的容器订阅它。

这是一个简单的示例,仅用于Console.WriteLine记录诊断内容。您应该将其替换为您希望用于应用程序的任何日志记录机制。

var tracer = new DefaultDiagnosticTracer();
tracer.OperationCompleted += (sender, args) =>
{
    Console.WriteLine(args.TraceContent);
};
container.SubscribeToDiagnostics(tracer);
Run Code Online (Sandbox Code Playgroud)