我在依赖链中有许多服务类(服务A依赖于服务B,它取决于服务C等);它们的行为由公共参数(CountryCode)确定,该参数是在运行时定义的可能支持的国家/地区。
注意:Actors可以扩展为多个实例(不同的线程),一个事件只能由一个actor处理,下面的服务是瞬态的(尽管我可以考虑在需要时更改它)。
目前我有这样的事情:
//This application flow starts off with this class
public class ActorExample
{
private IServiceOne _serviceOne; //Has dependent service
public async Task ProcessAsync(Event event)
{
//This value needs to be passed to _serviceOne and any children
//but we only know its value at runtime.
event.CountryCode;
}
}
public class ServiceOne : IServiceOne
{
private IServiceTwo _serviceTwo; //Has another nested dependency
//Implementation here varies depending on event.CountryCode
public async Task DoSomething()
}
public class ServiceTwo : IServiceTwo
{
//Implementation here varies depending on event.CountryCode
public async Task DoSomething()
}
我想我也许可以在服务中使用泛型,所以传递国家代码如下:
public class ServiceTwo<TCountryCode> : IServiceTwo<TCountryCode>
但是因为我们在运行时只有这个值,所以这是不可能的,特别是在注入服务时。
另一个解决方案是使用依赖的CountryCode注入服务为null,然后在构造函数中填充,如:
container.Register(Component.For<IActor>().ImplementedBy<Actor>()
.DependsOn(Dependency.OnValue("CountryCode", null));
然而,这似乎很麻烦而且很麻烦,特别是如果筑巢很深的话。
如果所有其他方法都失败了,我可能会考虑在调用函数之前设置商店,但我必须为每个函数执行此操作,例如:
_serviceOne.SetCountry(CountryCode).DoSomething();
注意:我们正在使用城堡进行IOC
答案 0 :(得分:3)
由于国家/地区代码是运行时数据,因此您应将其作为服务方法中的参数传递。
如果这是不可接受的,即无意义(例如从概念角度来看)更改方法签名以包含国家/地区代码,那么您可以将国家/地区代码存储在状态持有者(一个唯一负责的对象)中是知道“当前”国家代码),并且需要知道“当前”国家代码有权访问(通过依赖)此状态持有者。
本文详细解释了此模式与本文“控制共享状态:状态持有者模式”部分中的示例:http://www.dotnetcurry.com/patterns-practices/1367/data-encapsulation-large-csharp-applications
答案 1 :(得分:2)
这可以通过使用打字工厂来实现:
public interface IServiceOneFactory
{
IServiceOne Create(CountryCode countryCode);
}
public class ServiceOne : IServiceOne
{
public ServiceOne(IServiceTwo servicetwo, CountryCode countryCode)
{
}
}
public class ActorExample
{
private raedonly IServiceOneFactory factory;
public ActorExample(IServiceOneFactory factory)
{
this.factory = factory;
}
public async Task ProcessAsync(Event event)
{
var serviceOne = this.factory.Create(event.CountryCode);
}
}
ServiceTwo也一样......
注册:
kernel.AddFacility<TypedFactoryFacility>();
kernel.Register(Component.For<IServiceOneFactory>().AsFactory();
kernel.Register(Component.For<IServiceOne>().ImplementedBy<ServiceOne>());
kernel.Register(Component.For<IServiceTwo>().ImplementedBy<ServiceTwo>());
kernel.Register(Component.For<IActor>().ImplementedBy<Actor>());
更多信息:
https://github.com/castleproject/Windsor/blob/master/docs/typed-factory-facility-interface-based.md
修改强> 为避免代码重复,您可以创建通用工厂:
public interface IServiceFactory<T>
{
T Create(CountryCode countryCode);
}
public ActorExample(IServiceFactory<IServiceOne> factory)
{
this.factory = factory;
}
kernel.Register(Component.For(typeof(IServiceFactory<>)).AsFactory();