views:

129

answers:

1

Given registered services:

builder.RegisterType<Foo1>().Named<IFoo>("one").As<IFoo>();
builder.RegisterType<Foo2>().Named<IFoo>("two").As<IFoo>();
builder.RegisterType<Foo3>().Named<IFoo>("three").As<IFoo>();

Can I retrieve named implementations of IFoo interface by injecting something like Func<string, IFoo> ?

public class SomeClass(Func<string, IFoo> foo) {
    var f = foo("one");
    Debug.Assert(f is Foo1);

    var g = foo("two");
    Debug.Assert(g is Foo2);

    var h = foo("three");
    Debug.Assert(h is Foo3);
}

I know I can do it with Meta<>, but I don't want to use it.

+2  A: 

You could register your own resolving delegate like this:

builder.Register<Func<string, object>>(c =>
    {
        var cc = c.Resolve<IComponentContext>();
        return named => cc.Resolve<object>(named);
    });
Peter Lillevold
Great idea! Thanks :).
ppiotrowicz
Minor edit - the 'c' parameter is a temporary; you need to resolve IComponentContext if you want to hang onto it like this.c => { var cc = c.Resolve<IComponentContext>(); return named => cc.Resolve<IFoo>(named); }
Nicholas Blumhardt
@Nicholas: ah, of course, this is too easy to overlook :)
Peter Lillevold
Agreed - I'd like to find a way to make this easier to catch.
Nicholas Blumhardt
Why are you resolving the IComponentContext ? The parameter c is already IComponentContext. You can use it like this :builder.Register<Func<string, object>>(c => named => c.Resolve<object>(named));
@user137348 - as Nicholas mentions, the 'c' context is a temporary context instance. If you "store" that context in the lambda we're registering the lambda will not work as expected. By resolving 'IComponentContext' we'll get a "real" context that can be passed around.
Peter Lillevold