interface IState {
}
class GoodState: IState {}
class BadState: IState {}
class MoreState: IState {}
// I stuck at here... :(
interface StateAggregateService {
IState GoodState {get;}
IState BadState {get;}
IState MoreState {get;}
}
基本上,我想实现状态机模式。我想使用 autofac聚合服务扩展名自动为我创建一个工厂类。但是所有具体的状态类都继承自IState
接口,聚合服务扩展无法区分它们。
一种解决方法是定义一些虚拟接口,例如IGoodState
,该接口继承自IState
。问题在于,随着状态类数量的增加,虚拟接口数量的增加,我觉得这确实是一个愚蠢的主意。
是否可以将注册与属性名称相关联?
答案 0 :(得分:0)
一种方法是对您的IState
实现使用命名注册,对实现IStateAggregateService
的类使用属性注入。因此,对于聚合服务,您将:
interface IStateAggregateService
{
IState GoodState { get; }
IState BadState { get; }
IState MoreState { get; }
}
class StateAggregateService : IStateAggregateService
{
public IState GoodState { get; set; }
public IState BadState { get; set; }
public IState MoreState { get; set; }
}
,注册如下所示:
builder.RegisterType<GoodState>().Named<IState>("GoodState");
builder.RegisterType<BadState>().Named<IState>("BadState");
builder.RegisterType<MoreState>().Named<IState>("MoreState");
builder.Register(c => new StateAggregateService
{
GoodState = c.ResolveNamed<IState>("GoodState"),
BadState = c.ResolveNamed<IState>("BadState"),
MoreState = c.ResolveNamed<IState>("MoreState")
}).As<IStateAggregateService>();
请记住,这种方法每次在聚合服务中调用属性时都会返回相同的对象。
如果您每次调用属性都需要新的实例,则可以使用具有键注册和IIndex<TKey, TService>
界面的其他方法;注册看起来像这样:
builder.RegisterType<GoodState>().Keyed<IState>("GoodState");
builder.RegisterType<BadState>().Keyed<IState>("BadState");
builder.RegisterType<MoreState>().Keyed<IState>("MoreState");
builder.RegisterType<StateAggregateService>().As<IStateAggregateService>();
服务的实现
class StateAggregateService : IStateAggregateService
{
private readonly IIndex<string, IState> _states;
public IState GoodState => _states["GoodState"];
public IState BadState => _states["BadState"];
public IState MoreState => _states["MoreState"];
public StateAggregateService(IIndex<string, IState> states)
{
_states = states;
}
}
为使此方法更简洁,您可能希望使用一些枚举作为IState
实现的键,而不是string
。
此外,您可以摆脱StateAggregateService
并在需要的地方使用IIndex<TKey, TService>
作为工厂。
更新: 如评论中所述,的确,使用聚合服务无法实现您需要的解决方案。但是可以通过一些手动配准和反射来做类似的事情。对于以下接口和聚合器类:
interface IStateAggregateService
{
IState GoodState { get; }
IState BadState { get; }
IState MoreState { get; }
}
class StateAggregateService : IStateAggregateService
{
public IState GoodState { get; set; }
public IState BadState { get; set; }
public IState MoreState { get; set; }
}
您可以使用以下注册:
builder.RegisterType<GoodState>().Keyed<IState>("GoodState");
builder.RegisterType<BadState>().Keyed<IState>("BadState");
builder.RegisterType<MoreState>().Keyed<IState>("MoreState");
builder.Register(c =>
{
var serviceProps = typeof(StateAggregateService).GetProperties();
var service = new StateAggregateService();
foreach (var property in serviceProps)
{
property.SetValue(service, c.ResolveKeyed<IState>(property.Name));
}
return service;
}).As<IStateAggregateService>();
区别在于您需要创建一个实现您的聚合接口的类。此解决方案使用属性名称,因此您需要将其名称与类型保持相同,或准备自己的逻辑以将适当的实现分配给聚合器属性。