简体   繁体   中英

C# Simple Injector return dynamic Interface type

I created a couple data provider classes called Provider1 and Provider2, both of which implement an IProvider interface. The idea is that the Provider Instance will vary depending on certain conditions so I created a method in order to return the specific implementation of that interface:

public IProvider GetProvider()
{
    if(*logic*)
    {
        return new Provider1();
    }
    else 
    {
        return new Provider2();
    }
}

The problem is that both Providers have objects being instantiated via SimpleInjector and I don't want to have to return something like this:

return new Provider1(new Object1(), new Object2());

Here's an example of the Provider using Constructor Injection and the Interface:

public interface IProvider
{
    public object GetData();
}


public class Provider1 : IProvider
{
    private Object1 _object1;
    private Object2 _object2;

    public Provider1(Object1 object1, object2 object2)
    {
        _object1 = object1; 
        _object2 = object2;
    }

    public object GetData()
    {
         *Provider1 specific logic*
    }
}

Provider2 looks similiar to Provider1, but it contains different logic since it's a different Provider. I was initially trying something like:

return Activator.CreateInstance<Provider1>();

but this throws an exception that says "no parameterless constructor defined for this object". So my question is: how can I return an instance of Provider1 or Provider2 from a method expecting a return type of IProvider while using SimpleInjector? Can I register a the existing Container with this type at runtime or is that frowned upon? I'd like to be able to be able to call something like this from a "Client" without the client caring where the data comes from:

private IProvider _provider;
return _provider.GetData();

Thanks!

You need a provider factory, which you would register with SimpleInjector.

interface IProviderFactory
{
    IProvider GetProvider();
}

class ProviderFactory : IProviderFactory
{
    private readonly Object1 _object1;
    private readonly Object2 _object2;

    public ProviderFactory(Object1 object1, Object2 object2)
    {
        _object1 = object1; //injected
        _object2 = object2; //injected
    }

    public IProvider GetProvider()
    {
        if (*logic*)
        {
            return new Provider1(_object1, _object2);
        }
        else
        {
            return new Provider2(_object1, _object2);
        }
    }
}

Then in your composition root:

container.Register<IProviderFactory, ProviderFactory>();
container.Register<Object1, Object1>();
container.Register<Object2, Object2>();

You then inject the factory into whatever class needs to get provider instances and let it call the factory. The factory will use the dependencies provided by SimpleInjector and pass them along to the providers.

class Example
{
    private readonly IProviderFactory _providerFactory;

    public Example(IProviderFactory providerFactory)
    {
        _providerFactory = providerFactory;  //Injected
    }

    public void MainCode()
    {
        IProvider p = _providerFactory.GetProvider();
        var foo = p.GetDate();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM