Question

I'm debugging autofac issues in an application with quite a lot of modules. Is there a way to find out what module registered some registration? I'm looking at the ComponentRegistry of the container, but I can't find any information there.

EDIT: A clarification. I have a lot of modules in my solution:

public class MyModule : Autofac.Module {
    public override void Load(ContainerBuilder builder) {
        builder.RegisterType<MyConcreteType>().As<IMyInterface>();
    }
}

I then register in my container by scanning my assemblies:

var builder = new ContainerBuilder();
builder.RegisterAssemblyModules(/* Get all assemblies in base dir */);
var container = builder.Build();

Now, I have a lot of registrations. My question is "What Module registered MyConcreteType?". I would like to do something like container.ComponentRegistry.Registrations.Select(reg => new { reg.Service, reg.RegisteredBy }), where RegisteredBy is some magic property.

Was it helpful?

Solution

Ok, I am not a 100% sure what you mean, but I'll give it a go:

For debugging, the implemented type is displayed in the Registrations collection of the ComponentRegistry:

enter image description here

i.e. at index 0, the implementation type is CustomDataElement.

As what service type the implementation type is registered can be seen in a ComponentRegistrations Services collection.

Does that help? Can you give an example otherwise?

EDIT:

Got it... Try this:

var l = _container.ComponentRegistry.Registrations
    .SelectMany(r => r.Services.OfType<IServiceWithType>(), 
               (r, s) => new { r.Activator.LimitType, s.ServiceType });

Not sure whether it works 100% as expected, but it should get you there...

EDIT 2:

I misunderstood the question, didn't distinguish between the registered service and the registering module. I don't think it is possible out of the box, as it would either require passing the module as an argument or Autofac to reflect the caller upon registration. Both is not the case, as far as I can tell. I can't find any built in features in Autofac.

If you can modify the modules, one approach would be to register the types with metadata. You probably know the approach, it is something like

public class MyModule: Autofac.Module
{
    public override void Load(ContainerBuilder builder) 
    {
        builder.RegisterType<MyConcreteType>()
               .As<IMyInterface>()
               .WithMetadata<IRegisteredByModuleMetadata>(m =>
                    m.For(am => am.RegisteringModuleType, GetType());;
    }
}

with the metadata interface

public interface IRegisteredByModuleMetadata
{
    Type RegisteringModuleType { get; set; }
}

Then in the container, resolving with metadata will allow to access the module types via the registrations Metadata property. Depending on your requirements you could simplify the type registration by providing a protected type registration method on a custom module base class which automatically appends the metadata, so you don't have to repeat yourself here.

If modifying every module in your solution is an option, that's probably not a bad way to go. Sorry I can't give any out-of-the-box solution. There might be one, I am missing, but that's all I can do for you here. Hope it helps nonetheless.

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