C#Simple Injector返回动态接口类型

时间:2017-08-15 22:08:53

标签: c# .net interface simple-injector

我创建了一些名为Provider1和Provider2的数据提供程序类,它们都实现了IProvider接口。我们的想法是提供者实例将根据特定条件而有所不同,因此我创建了一个方法以返回该接口的特定实现:

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

问题是两个Providers都有通过SimpleInjector实例化的对象,我不想返回这样的东西:

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

以下是使用构造函数注入和接口的提供程序示例:

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看起来与Provider1类似,但它包含不同的逻辑,因为它是不同的Provider。我最初尝试的是:

return Activator.CreateInstance<Provider1>();

但是这会抛出一个异常,说“没有为此对象定义无参数构造函数”。所以我的问题是:如何在使用SimpleInjector时从期望返回类型为IProvider的方法返回Provider1或Provider2的实例?我可以在运行时注册这种类型的现有Container,还是不赞成?我希望能够在没有客户端关注数据来源的情况下从“客户端”调用此类内容:

private IProvider _provider;
return _provider.GetData();

谢谢!

1 个答案:

答案 0 :(得分:1)

您需要一个提供者工厂,您可以使用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);
        }
    }
}

然后在你的作文根:

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

然后,您将工厂注入需要获取提供程序实例的任何类,并让它调用工厂。工厂将使用SimpleInjector提供的依赖项并将它们传递给提供程序。

class Example
{
    private readonly IProviderFactory _providerFactory;

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

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