Resolving AutoFac dependencies inside Module class

孤街浪徒 提交于 2019-12-04 23:07:32

When registering something within your modules with autofac instead of using RegisterType method you might use Register method:

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

The answer turned out to be incredibly simple. I just added IComponentContext as a dependency to my Module's implementation

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

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

And let AutoFac inject the IComponentContext for me. That way I can resolve any dependencies I require inside the module.

Rule of thumb for using every IoC/DI Container: Resolve once! => then you get all dependencies resolved for your requested object. If you try to resolve multiple times, register other objects (in the meantime) you're stuck in hell. Really. If you want to retrieve objects for different purposes at different places and time points (resolved from central registration) you may be looking for the Service Locator Pattern instead (but this is often described as an Anti-Pattern, too).

Modules have the purpose to bundle related registrations (conditionally) as statet in the Autofac documentation:

A module is a small class that can be used to bundle up a set of related components behind a ‘facade’ to simplify configuration and deployment.

... so if they are just a sum of registrations and the container has not yet been build you are not able to resolve and use an (even previously registered) component immediately (except calling a method on the registrant itself through OnActivate* hooks or when using instance registration, but I think this is not the case for your example). The components are just in the state of registration but the complete context is not ready for resolving. What would happen if you override the registration in another Module? Then you would have injected different objects... bad idea. Maybe you should rethink your application design and which objects have which responsibilities.

By the way: Logging is a cross cutting concern that is often "injected / resolved" by calling a separate static factory or service instead of doing constructor / property injection (see usage of Common.Logging for example).

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
    }
}

You can also try to use AOP libraries and weave the dependency into the Module (using reflection). But I don't think it's worth to try just for logging in a Module.

Anyway: @mr100 has already shown the right usage during registration. There you can also handle activation etc. but not do logging for the Module itself.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!