【发布时间】:2015-04-20 08:43:56
【问题描述】:
我在我的逻辑层中使用以下接口来强制执行单一职责(可能会被破坏,但你必须跳过障碍,让自己非常头疼才能实现这一点)。
public interface ILogic<in TContext, out TOutput>
{
#region Execute
TOutput Execute(TContext context);
#endregion
}
假设有以下内容:
[DataContract]
public class CompanyRequest : ExtensibleDataObject
{
#region Properties
[DataMember(IsRequired = true)]
public string Number { get; set; }
[DataMember(IsRequired = true)]
public Entity Entity { get; set; }
[DataMember(IsRequired = true)]
public CompanyOptions Options { get; set; }
#endregion
}
和
[DataContract]
public class CompanyResponse : ExtensibleDataObject
{
[DataMember]
public Company Company { get; set; }
// TODO: Store any errors occurred for graceful handling
//..
//..
}
Company DataContract 将包含通过 CompanyOptions 枚举请求的数据,最终会有 30 - 50 个此类属性。
我意识到 Aufofac 不可能注入仅包含构造所需的逻辑实例的列表,但我确实通过 IIndex 知道,公司运营合同或其他名称(目前尚待讨论)可以获得IIndex 在构造期间存储并通过元数据或其他方式存储,例如它可以执行 Where(registration => context.Flags.HasFlag(logic.Metadata.Flag) 留下负责满足调用的逻辑实现列表。(我的解释可能是错误的,而且漏洞百出)
我的问题是处理这种行为的首选方法是哪种。理想情况下,我会完全避免元数据,因为我是一个团队的一员,该团队的工作是引入一个自定义 nuget 服务器,我们通过该服务器审查和控制允许团队使用哪些包,所以对我来说继续开始有点讽刺添加新的包,例如 Aufofac.Extras.Metadata 包。
逻辑注册是通过属性自动/选择加入的:
[Logic(Entity.Uk, CompanyDetail.PaymentTrends)]
public class PaymentTrends : ILogic<CompanyRequest, NullLogicResponse>
{
public NullLogicResponse Execute(CompanyRequest request)
{
throw new NotImplementedException();
}
}
每个向 Autofac 注册的程序集都是通过这样的模块进行的:
public class LogicAutofacModule : Module
{
#region Load
protected override void Load(ContainerBuilder builder)
{
// ReSharper disable once IteratorMethodResultIsIgnored
builder.RegisterTypesWithAttribute<LogicAttribute>(typeof(ILogic<,>));
builder.RegisterAssemblyModules<DataAutofacModule>();
}
#endregion Load
}
RegiserTypesWithAttribute 如下所示:
public static class ContainerBuilderRegisterTypesWithAttribute
{
#region RegisterTypesWithAttribute
public static IEnumerable<IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle>> RegisterTypesWithAttribute<TAttribute>(this ContainerBuilder builder, Type typeBeingRegistered) where TAttribute : Attribute
{
var assembly = typeof(TAttribute).Assembly;
// ReSharper disable once LoopCanBeConvertedToQuery ... no thanks!
foreach (var type in assembly
.GetTypes()
.Where(type => type.HasCustomAttribute<TAttribute>()))
{
var registration = builder.RegisterType(type)
.As(type.GetInterfaces()
.First(i =>
i.IsGenericType &&
i.GetGenericTypeDefinition() == typeBeingRegistered));
yield return registration;
}
}
#endregion
}
我还不知道注册类型及其元数据的最佳方式。 LogicAttribute 公开了一个由实体和标志组成的元数据属性。我猜可以将键控排除在字符串之外吗?我也应该使用 IIndex 然后确保我的构造函数的参数看起来与此类似:
public LogicDispatcher(IEnumerable>Lazy<Meta<LogicMetadata, ILogic<NullLogicResponse, CompanyRequest>>> logicEnumerable)
{
_logicEnumerable = logicEnumerable;
}
然后在它的 Execute 方法中:
public NullLogicResponse Execute(CompanyRequest request)
{
var applicableLogic =
_logicEnumerable.Where(metadata => metadata.HasFlag(request.Flag);
foreach (var logic in applicableLogic)
{
logic.Execute(request)
}
}
对于改进上述内容和/或处理手头问题的更好方法的任何帮助将不胜感激。谢谢。
附言
将有 30 个具有相同类型的 ILogic 接口并且不断增长。例如,每个都将/可能通过 TPL 被解雇,所以我很高兴一次收到 X 个注册。
【问题讨论】:
-
各位,我是不是措辞太差,让你们无法理解这个问题?