我们有一种情况,我们使用Castle Windsor依赖注入将IService
注入到wep api控制器中,如下所示:
public FooController : ApiController
{
private IService _service;
public FooController(IService service)
{
_service = service;
}
}
注册这样的服务:
container.Register(Component.For<IService>().ImplementedBy<Service>().LifestyleTransient());
服务类似于:
public Service : IService
{
public virtual string Logic()
{
return "Service Logic";
}
}
问题是,一些客户的业务逻辑与基础业务逻辑完全不同,因此我们需要使用Service
的另一种实现来满足客户的需求。
因此,如果有2个客户(Customer1和Customer2),则Customer1应使用默认的Service
,但Customer2应使用名为Customer2Service
的自定义实现,该实现将从Service
继承并覆盖像这样需要:
public Customer2Service : Service
{
public override string Logic()
{
var response = base.Logic();
return "Customer 2 Logic " + response;
}
}
问题
我们尝试了什么
我们尝试将依赖注入更改为基于属性,如下所示:
public FooController : ApiController
{
private IService _service;
public FooController()
{
}
public HttpResponseMessage FooAction(string customer)
{
_service = container.Resolve<IService>(customer);
...
}
}
container.Register(Component.For<IService>().ImplementedBy<Service>().LifestyleTransient());
container.Register(Component.For<IService>().ImplementedBy<Customer2Service>().LifestyleTransient().Named("Customer2"));
问题在于,我们必须为每个客户提供定制服务,即使他们不需要它也可能会变得笨拙。否则,解决方案会抛出一个异常,说明命名的依赖关系不存在。
答案 0 :(得分:0)
您可以在这里使用工厂:
class ServiceFactory : IServiceFactory
{
public IService GetService(string customer)
{
switch (customer)
{
case "special":
return container.Resolve<IService>("special");
default:
return container.Resolve<IService>("default");
}
}
}
然后您可以将工厂注入您的控制器并从工厂获得IService
。
在switch语句中,您只声明特殊情况,所有其他情况都是默认子句。
答案 1 :(得分:0)
我建议将客户特定的实施保留在不同的项目中。例如,您可以拥有一个名为CoreServices
且具有基本功能的项目:
namespace CoreServices.Services
{
public interface IServiceA
{
string Test { get; }
}
public interface IServiceB
{
string Test { get; }
}
public class ServiceA : IServiceA
{
public virtual string Test
{
get { return "CoreServices: ServiceA"; }
}
}
public class ServiceB : IServiceB
{
public virtual string Test
{
get { return "CoreServices: ServiceB"; }
}
}
}
另一个项目名称CostomerAServices
,其中只定制了ServiceA
:
namespace CustomerAServices.Services
{
public class ServiceA : CoreServices.Services.ServiceA
{
public override string Test
{
get { return "CustomerAServices: ServiceA"; }
}
}
}
然后,通过运行此代码,您将获得所需内容:
string customizedAssemblyName = "CustomerAServices"; // Get from config
container.Register(Classes
.FromAssemblyNamed(customizedAssemblyName)
.InNamespace(customizedAssemblyName + ".Services")
.WithServiceAllInterfaces());
container.Register(Classes
.FromAssemblyNamed("CoreServices")
.InNamespace("CoreServices.Services")
.WithServiceAllInterfaces());
首先,您将注册自定义版本和基本版本。因此,如果您运行此代码:
var serviceA = container.Resolve<IServiceA>();
System.Console.WriteLine(serviceA.Test);
var serviceB = container.Resolve<IServiceB>();
System.Console.WriteLine(serviceB.Test);
输出将是:
CustomerAServices: ServiceA
CoreServices: ServiceB