解决Module类中的AutoFac依赖项

时间:2014-05-01 14:19:20

标签: c# dependency-injection autofac

我是AutoFac的新手,目前我在app app中使用自定义模块来启动一些核心F#系统。我使用的代码是

var builder = new ContainerBuilder();
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>();
builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
builder.Build();

在我的app配置中,我有适当的逻辑来启动相关系统。我想访问我的模块中的DefaultLogger。 Module基类的元数据有以下选项可供我使用:

protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration);

protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource);

public void Configure(IComponentRegistry componentRegistry);

protected virtual void Load(ContainerBuilder builder);

到目前为止我只使用了Load,但我无法在构建器上看到任何可以让我进入日志记录服务的方法。

3 个答案:

答案 0 :(得分:6)

使用autofac而不是RegisterType方法在模块中注册某些内容时,可以使用Register方法:

builder.Register(c =>
   {
       IComponentContext ctx = c.Resolve<IComponentContext();
       IDefaultLogger logger = ctx.Resolve<IDefaultLogger>();
       ...do something with logger...
       return ...return object you want to register...;
    });

答案 1 :(得分:3)

答案结果非常简单。我刚刚将IComponentContext添加为我的Module的实现

public class LocalActorSystemModule : Module {
    private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module

    public LocalActorSystemModule(IComponentContext componentContext) { 
        m_ComponentContext = componentContext;
    }

让AutoFac为我注入IComponentContext。这样我就可以解决模块内部所需的任何依赖项。

答案 2 :(得分:2)

使用每个IoC / DI 容器的经验法则:解析一次! =&gt;然后,您将获得所请求对象的所有依赖项。如果你试图多次解决,注册其他对象(在此期间)你陷入了地狱。真。如果您想在不同的地点和时间点(从中央注册中解析)检索不同目的的对象,您可能正在寻找Service Locator Pattern(但这也经常被描述为Anti-Pattern)。

模块的目的是将相关注册(有条件地)捆绑为Autofac documentation中的statet:

  

模块是一个小类,可用于捆绑一组   “Facade”背后的相关组件,以简化配置和   部署。

...因此,如果它们只是注册的总和而且容器尚未构建,则您无法立即解析并使用(甚至以前注册过的)组件(除了通过OnActivate在注册人自己调用方法之外) *钩子或使用实例注册时,但我认为这不是你的例子的情况)。组件处于注册状态,但完整的上下文尚未准备好解决。如果您覆盖另一个模块中的注册会发生什么?然后你会注入不同的对象......糟糕的主意。也许您应该重新考虑您的应用程序设计以及哪些对象具有哪些职责。

顺便说一句:日志记录是一个跨领域的问题,通常通过调用单独的静态工厂或服务而不是进行构造函数/属性注入来“注入/解决”(例如,参见Common.Logging的用法)。 / p>

public class MyModule : Module
{
    private static readonly ILog Log = LogManager.GetLogger<MyModule>();

    protected override void Load(ContainerBuilder builder)
    {
        Log.Debug(msg => msg("Hello")); // log whatever you want here
    }
}

您还可以尝试使用 AOP 库并将依赖项编织到模块中(使用反射)。但我认为仅仅尝试登录模块是不值得的。

无论如何:@ mr100在注册时已经显示正确的用法。在那里你也可以处理激活等但不能记录模块本身。