Можно ли удалить существующую регистрацию с автозагрузчика Autofac?

Что-то в этих строках:

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

Сценарий: я просматриваю кучу сборок, и когда я иду, я регистрирую типы, но я хочу убедитесь, что у меня есть только одна реализация данного типа. Мне нужно сделать это, прежде чем я создам контейнер. Я мог бы отследить это самостоятельно, но было бы неплохо, если бы Autofac мог мне немного помочь.

Ответ 1

Это невозможно сделать непосредственно с помощью ContainerBuilder, если только вы не начнете новый. Имейте в виду, что, сначала построив контейнер, вы сможете построить новый контейнер, отфильтровывающий нежелательные типы и повторное использование регистраций из первого контейнера. Вот так:

...
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 c.ComponentRegistry.Sources)
{
    cb.RegisterSource(source);
}

container = builder.Build();

Это не очень элегантный, но он работает. Теперь, если вы можете подробно остановиться на , почему, вы хотите сделать это, возможно, есть лучший способ.

Ответ 2

Питер Л., вероятно, получил самый простой вариант.

Чтобы обойти проблему в целом, можете ли вы изменить способ обнаружения компонентов для их фильтрации до регистрации? Кажется, что должен быть подход, который обойдет это... Кроме того, может быть сложной задачей в дальнейшем отслеживать, какие компоненты сохранить и что удалить.

Более сложный подход состоит в том, чтобы переопределить поддержку IEnumerable, чтобы отфильтровать те вещи, которые вы не хотите. То есть скопируйте и измените этот код, чтобы создать FilteredCollectionSource, который исключает компоненты, которые вам не нужны.

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

станет:

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

Если вы добавите FilteredCollectionSource к строителю с помощью RegisterSource(), он будет использоваться вместо встроенного.