如何使用相同服务的某些提供商?

时间:2011-06-27 14:16:41

标签: c# architecture ioc-container

我注册了服务&提供者使用一些IoC工具(例如StructreMap)

public interface IProvider
{
    void Load(int id);
}
public class Provider : IProvider
{
     public void Load(int id) {...} 
}
public interface IService
{
    void Load(int id);
}
public class Service : IService
{
    public Service(IProvider provider) { }
    public void Load(int id) { provider.Load(id); }
}

现在我有另一家提供商

public class Provider2 : IProvider
{
    public void Load(int id) {...}
}

我想注册该提供程序(Provider2)并从IoC工具获取带有Provider2的Service实例。我能看到这样做的唯一方法是创建将继承自IService2的Service2,并且最后一个将继承自IService。现在我可以获得IService2类型的实例,它将使用Provider2启动提供程序。

public interface IService2 : IService
{ }
public class Service2 : IService2
{
    public Service2(IProvider2 provider) { }
    public void Load(int id) { provider.Load(id); }
}

我的问题是:对于每个新的提供商,我需要为服务编写新类,即使服务的功能应该保持不变?

1 个答案:

答案 0 :(得分:1)

不,你不需要这样做。

我建议你实现一个抽象工厂模式,根据运行时知道的值选择正确的提供者实现。

有关示例,请查看此处:http://alsagile.com/archive/2010/06/28/Abstract-Factory-and-IoC-Container-in-asp-net-MVC.aspx

它位于MVC上下文中,但可以在其他场景中轻松实现。

示例:

您可以像这样注册您的服务(伪代码):

x.For<IService>().Use<Service>();    
x.For<IProvider>().Use<Provider1>().Named("provider1");
x.For<IProvider>().Use<Provider2>().Named("provider2");

您需要一种方法在Abstract工厂中注入容器。你可以这样包装它:

public interface IProviderFactory
{    
    object GetInstance<IProvider>();    
    object GetNamedInstance<IProvider>(string key);
}

实施:

public class ProviderFactory : IProviderFactory
{     
    private readonly Container _container     
    public ProviderFactory (Container container)     
    {          
        _container = container;     
    }     
    ...
}

并设置StructureMap以解决与抽象工厂的依赖关系:

x.For<IProviderFactory>.Use(new ProviderFactory(this));

然后进入您的服务,您应该像这样注入提供者工厂

public class Service : IService
{
    private readonly IProviderFactory _providerFactory;

    public Service(IProviderFactory factory)
    {
        if (factory == null)
            throw new ArgumentNullException("factory", "providerfactory cannot be null");
        _proiderFactory = factory;
    }

    public void Load(string providerName)
    {
      var provider = _providerFactory.GetNamedInstance(providerName);
      // do some operation on provider
    }
}

这应该有用。