首页 > 解决方案 > Autofac,从随机组件访问 ContainerBuilder

问题描述

我正在使用 Autofac,假设我的应用程序中有一个使用 Logging 的组件(DLL)。记录的方式和地点将由主应用程序定义。所以它向 Autofac 注册了 ILog 接口。

问题是我的组件如何访问 ContainerBuilder 对象来解析 ILog?

我总是可以用 IContainer 初始化我的组件,但这违背了目的。我只是将 ILog 接口传递给组件而不是 IContainer。

标签: autofac

解决方案


如果我正确地理解了你在哪里 - 值得阅读“Composition Root”以了解如何总体上考虑这一点。简短的回答是“你不能Container从组件中访问 s”。

https://blog.ploeh.dk/2011/07/28/CompositionRoot/

正如您所说,您的组件不应该对 Autofac 有任何了解——这实际上适用于您的所有代码,除了主应用程序中的一小部分。那么 ILog 是如何找到您的组件的呢?从马克·西曼的帖子中:

“这意味着所有应用程序代码都完全依赖于构造函数注入”

即使您没有使用 DI 框架,这是使您的代码更清晰的一个很好的一般规则。因此,在您的情况下,假设您有一个非常简单的应用程序,如下所示:

class Program
{
    static void Main(string[] args)
    {
        var component = new Component();    // we want logging to happen inside here
        component.DoStuff();
        Console.ReadKey();
    }
}

您实际上只是想将您添加ILog为对您的依赖项Component,然后将其注入尽可能接近您的应用程序入口点:

public class Component
{
    private readonly ILog _logger;

    public Component(ILog logger)
    {
        _logger = logger;
    }

    public void DoStuff()
    {
        _logger.Log("this is a test");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var container = GetContainer();
        using (var scope = container.BeginLifetimeScope())  
        {
            var test = scope.Resolve<Component>();          // this is potentially the only place we need to resolve anything
            test.DoStuff();
        }
        Console.ReadKey();
    }

    private static IContainer GetContainer()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<Component>();
        builder.RegisterType<Logger>()
            .As<ILog>();
        var container = builder.Build();
        return container;
    }
}


推荐阅读