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

时间:2013-09-02 18:25:30

标签: logging dependency-injection autofac

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

是否有记录Autofac无法解决的所有请求?或者只是将所有请求记录到容器中?

3 个答案:

答案 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事件记录信息后,您会看到异常弹出,您将知道哪个组件正在抛出。

如果您想获得更好的体验,可以在容器ChildLifetimeScopeBeginningResolveOperationBeginningResolveOperationEndingCurrentScopeEnding事件上设置一些事件处理程序。

  • 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);