Можно ли удалить существующую регистрацию из Autofac контейнерного конструктора? - PullRequest
12 голосов
/ 23 февраля 2011

Что-то в этом роде:

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 мог мне немного помочь.

Ответы [ 2 ]

12 голосов
/ 24 февраля 2011

Это нельзя сделать напрямую с помощью 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 container.ComponentRegistry.Sources)
{
    cb.RegisterSource(source);
}

container = builder.Build();

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

1 голос
/ 24 февраля 2011

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

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

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

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

станет:

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

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

...