我注册了服务&提供者使用一些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); }
}
我的问题是:对于每个新的提供商,我需要为服务编写新类,即使服务的功能应该保持不变?
答案 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
}
}
这应该有用。