我是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,我在构建器上看不到任何允许我进入日志记录服务的方法。
使用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...;
});
答案结果非常简单。我刚刚将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。这样我就可以解决模块内部所需的任何依赖关系。
使用经验法则 每个IoC / DI 容器: 解决一次! =>然后,您将获得所请求对象的所有依赖项。如果你试图多次解决,注册其他对象(在此期间)你陷入了地狱。真。如果您想在不同的地点和时间点(从中央注册解决)检索不同目的的对象,您可能正在寻找 服务定位器模式 相反(但这通常被描述为 反模式,也)。
模块的目的是将相关的注册(有条件地)捆绑为 Autofac文档:
模块是一个小类,可用于捆绑一组
“Facade”背后的相关组件,以简化配置和
部署。
...因此,如果它们只是注册的总和并且容器尚未构建,则您无法立即解析并使用(甚至以前注册过的)组件(除了通过OnActivate *钩子调用注册人本身的方法或当使用实例注册时,但我认为这不是你的例子的情况)。组件处于注册状态,但完整的上下文尚未准备好解决。如果您覆盖另一个模块中的注册会发生什么?然后你会注入不同的对象......糟糕的主意。也许您应该重新考虑您的应用程序设计以及哪些对象具有哪些职责。
顺便说一句:日志记录是一个跨领域的问题,通常通过调用单独的静态工厂或服务而不是进行构造函数/属性注入来“注入/解决”(请参阅 Common.Logging 例如)。
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已经在注册期间显示了正确的用法。在那里你也可以处理激活等但不能记录模块本身。