Замок Виндзор: Использование регистрации конвенций вместе с конкретными реализациями - PullRequest
5 голосов
/ 07 января 2011

Предположим, что IFoo реализован Foo, а IBar реализован FirstBar и SecondBar.

Используя эту регистрацию соглашения:

container.Register(
    AllTypes.FromThisAssembly().Pick()
        .WithService.DefaultInterface())

В контейнере будет три записи:

IFoo = Foo
IBar = FirstBar
IBar = SecondBar

Теперь, как мы можем настроить эту регистрацию, чтобы сообщить контейнеру, что для IBar мы хотим, чтобы SecondBar был зарегистрирован только?Сортировка:

container.Register(
    AllTypes.FromThisAssembly().Pick()
        .WithService.DefaultInterface()
        .For<IBar>().Select<SecondBar>())

Вариант использования: в нашем приложении есть множество сервисов, все они зарегистрированы в соответствии с соглашениями.Однако некоторые из сервисных интерфейсов имеют две или более реализации (например, реальная реализация, поддельная реализация и тестовая реализация).Регистрация конвенции зарегистрирует их всех под одним и тем же интерфейсом, и при разрешении интерфейса мы получим первую реализацию (в недетерминированном порядке).Мы хотим иметь возможность выбрать одну конкретную реализацию для этих сервисов при регистрации.Как мы можем это сделать?

Ответы [ 2 ]

5 голосов
/ 08 января 2011

Затяните свое соглашение. Это, очевидно, широкий.

container.Register(
    AllTypes.FromThisAssembly()
        .Where(t => t.Namespace != "Acme.Tests")
        .WithService.DefaultInterface())
3 голосов
/ 12 января 2011

Вот что сделало работу:

container.Register(
    AllTypes.FromThisAssembly().Pick()
        .WithService.DefaultInterface())
        .ConfigureFor<IBar>(c => 
            c.If((k, m) => m.Implementation == typeof(SecondBar)));

Это эффективно регистрирует только SecondBar для службы IBar. Таким образом, если для данной службы существует более одной реализации, мы можем указать обычному сканеру, какой нам нужен.

Мы пошли дальше и создали для этого приятные маленькие методы расширения:

public static BasedOnDescriptor Select<TService, TImpl>(this BasedOnDescriptor desc)
{
    return desc.ConfigureFor<TService>(c => c.If((k, m) => m.Implementation == typeof(TImpl)));
}

public static BasedOnDescriptor Ignore<TService>(this BasedOnDescriptor desc)
{
    return desc.ConfigureFor<TService>(c => c.If((k, m) => false));
}

Теперь мы можем использовать его так:

container.Register(
    AllTypes.FromThisAssembly().Pick()
        .WithService.DefaultInterface())
        .Select<IBar, SecondBar>()
        .Ignore<ISomeService>()

В целом все это работает хорошо. Я считаю, что эти два метода могут быть в замке. Виндзор собственно. @Krzysztof Koźmic: куда я могу отправить патч? :)

...