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

本文关键字:提供商 服务 何使用 | 更新日期: 2023-09-27 18:00:34

我注册服务&提供一些IoC工具(例如StructeMap)

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); }
}

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

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

不,您不需要这么做。

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

例如,请查看此处: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");

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

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
    }
}

这应该行得通。