Question

I've read over several examples that were more complex then I needed and I'm having trouble distilling this down to a simple, concise pattern.

Let's say I have an interface names ICustomService and multiple implementations of ICustomService. I also have a class Consumer that needs to determine at run time which ICustomService to use based upon a parameter.

So I create a classes as follows:

public class Consumer
{
    private CustomServiceFactory customServiceFactory;

    public Consumer(CustomServiceFactory _customServiceFactory)
    {
        customServiceFactory = _customServiceFactory;
    }

    public void Execute(string parameter)
    {
        ICustomService Service = customServiceFactory.GetService(parameter);
        Service.DoSomething();
    }
}

public class CustomServiceFactory
{
    private IComponentContext context;
    public CustomServiceFactory(IComponentContext _context)
    {
        context = _context;
    }

    public ICustomService GetService(string p)
    {
        return context.Resolve<ICustomService>(p);  // not correct 
    }
}

public class ServiceA : ICustomService
{
    public void DoSomething()
    {

    }
}

public class ServiceB : ICustomService
{
    public void DoSomething()
    {

    }
}

Is there an advantage to having my factory implement an interface? How do I fix my factory and register these classes with Autofac so that Consumer.Execute("A") calls DoSomething on WorkerA and Consumer.Execute("B") calls DoSomething on WorkerB?

Thank you

Was it helpful?

Solution

You would register your implementations of ICustomService with keys. For example:

builder.RegisterType<FooService>.Keyed<ICustomService>("someKey");
builder.RegisterType<BarService>.Keyed<ICustomService>("anotherKey");

and then your factory method would be:

public ICustomService GetService(string p)
{
    return context.ResolveKeyed<ICustomService>(p);
}

But, you can take this a step further and decouple CustomServiceFactory from IComponentContext:

public class CustomServiceFactory
{
    private Func<string, ICustomService> _create;

    public CustomServiceFactory(Func<string, ICustomService> create)
    {
        _create = create;
    }

    public ICustomService GetService(string p)
    {
        return _create(p);
    }
}

which you would register like so:

builder.Register(c => {
    var ctx = c.Resolve<IComponentContext>();
    return new CustomServiceFactory(key => ctx.ResolveKeyed<ICustomService>(key));
});

And at that point, assuming CustomServiceFactory doesn't have any other behavior that was omitted for the question, then you as might as well just use and register Func<string, ICustomService> directly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top