Question

I'm new to AutoFac and am currently using custom modules inside my app config to boot up some core F# systems. The code I'm using is

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

And inside my app config I have the appropriate logic to start up the relevant systems. I would like to have access to the DefaultLogger inside my Modules. Metadata for the Module base class has the following options available to me:

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

I've only been using Load so far and I can't see any methods on the builder that would allow me to get at the logging service.

Was it helpful?

Solution 2

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.

OTHER TIPS

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...;
    });

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top