Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to remove an existing registration from Autofac container builder?

Tags:

c#

autofac

Something along those lines:

builder.RegisterType<MyType>().As<IType>();
builder.RegisterType<MyType2>().As<IType>();
builder.DeRegisterType<MyType>().As<IType>()

var container = builder.Build();
var types = container.Resolve<IEnumerable<IType>>();
Assert.IsTrue(types.Count == 1);
Assert.IsTrue(types[0].GetType == typeof(MyType2));

Scenario: I go through bunch of assemblies and as I go I register types but I want to make sure that I have only one implementation of a given type. I need to do this before I create the container. I could track that on my own but it would be nice if Autofac could help me a bit.

like image 620
Pawel Pabich Avatar asked Feb 23 '11 12:02

Pawel Pabich


People also ask

Does Autofac use reflection?

You register components with Autofac by creating a ContainerBuilder and informing the builder which components expose which services. Components can be created via reflection (by registering a specific .


2 Answers

This cannot be done directly using the ContainerBuilder, unless you start over with a new one. Mind you, having first built a container you should be able to construct a new container filtering away unwanted types and reusing the registrations from the first container. Like this:

...
var container = builder.Build();

builder = new ContainerBuilder();
var components = container.ComponentRegistry.Registrations
                    .Where(cr => cr.Activator.LimitType != typeof(LifetimeScope))
                    .Where(cr => cr.Activator.LimitType != typeof(MyType));
foreach (var c in components)
{
    builder.RegisterComponent(c);
}

foreach (var source in container.ComponentRegistry.Sources)
{
    cb.RegisterSource(source);
}

container = builder.Build();

This is hardly very elegant but it works. Now, if you could elaborate on why you want to do this, perhaps there is a better way.

like image 139
Peter Lillevold Avatar answered Oct 31 '22 16:10

Peter Lillevold


Peter L.'s probably got the most straightforward option.

To get around the problem altogether, can you modify the way you're discovering components to filter them in advance of registration? It does seem like there must be an approach that gets around this... It also might be a challenge further down the track to work out which components to keep vs. which to remove.

A more involved approach is to override IEnumerable support to filter out the the things you don't want. I.e. copy and modify this code to create a FilteredCollectionSource that excludes the components you don't want.

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService);

would become:

var elements = c.ComponentRegistry.RegistrationsFor(elementTypeService)
    .Where(reg => /* not a duplicate */);

If you add your FilteredCollectionSource to the builder using RegisterSource() it will should get used instead of the built-in one.

like image 34
Nicholas Blumhardt Avatar answered Oct 31 '22 16:10

Nicholas Blumhardt