Можно ли удалить существующую регистрацию с автозагрузчика 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()
, он будет использоваться вместо встроенного.