Castle Windsor: Using convention registration along with specific implementations

百般思念 提交于 2019-12-19 03:25:11

问题


Assume we have IFoo implemented by Foo and IBar implemented by FirstBar and SecondBar.

Using this convention registration:

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

We'll have three entries in the container:

IFoo = Foo
IBar = FirstBar
IBar = SecondBar

Now, how can we tweak this registration to be able to tell the container that for IBar we want SecondBar registered only? Sort of:

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

Use case: we have lots of services in our app all registered by conventions. However, some of the service interfaces have two or more implementations (e.g. real implementation, fake implementation and test implementation). Convention registration will register them all under the same interface and while resolving the interface we'll get the first implementation (in nondeterministic order). We want to be able to select one specific implementation for those services while registering. How can we do that?


回答1:


Tighten your convention. It is obviously to wide.

container.Register(
    AllTypes.FromThisAssembly()
        .Where(t => t.Namespace != "Acme.Tests")
        .WithService.DefaultInterface())



回答2:


This is what made the work done:

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

This effectively registers only SecondBar impl for IBar service. This way, if there is more than one implementation for given service, we can tell the conventional scanner which impl we want.

We went ahead and created nice little extension methods for this purpose:

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

We can now use it like this:

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

All in all this works nicely. I believe those two methods could be in the Castle.Windsor proper. @Krzysztof Koźmic: where do I submit a patch? :)



来源:https://stackoverflow.com/questions/4627027/castle-windsor-using-convention-registration-along-with-specific-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!