Domanda

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

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top