我正在使用命令处理程序模式,并与ninect.extensions.Conventions进行绑定,当我的实际IQueryHandler<,>接口实现匹配单个具体类型时,这种方式非常有效。这是我正在使用的内容:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IQueryHandler<,>))
.BindSingleInterface()
.Configure(b => b.WhenInjectedInto(typeof(ValidationHandlerDecorator<,>)).InRequestScope()));
kernel.Bind(typeof(IQueryHandler<,>)).To(typeof(PerformanceHandlerDecorator<,>)).InRequestScope();
但我遇到了这样一种情况:根据自定义路由值,在运行时需要覆盖默认的具体类型。以下内容可以正常工作:
kernel.Bind<IQueryHandler<query1, result1>>().ToMethod(
context => HttpContext.Current.Request.RequestContext.RouteData.Values["type"].ToString().ToLower() == "api"
? (IQueryHandler<query1, result1>)new apiHandler()
: (IQueryHandler<query1, result1>)new defaultHandler()
)
上述代码的问题在于,我需要为每个IQueryHandler<,>泛型类型编写此代码。此外,对于每个我想要全局应用的装饰器(如顶部示例),我都需要修改每个绑定并添加它,从而使代码翻倍或翻三倍。
我希望实现的目标是使用以下内容。 我已经实现了一个类/接口来返回自定义路由数据值。 这可以运行,但会抛出异常,因为在运行时HttpContext.Current为空。 我认为这是因为它在运行时不会按请求解析。
kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IQueryHandler<,>))
.StartingWith(kernel.Get<IMyContext>().customRouteValue) // this isn't valid...
.BindSingleInterface()
.Configure(b => b.InRequestScope())
);
有没有办法使用"ToMethod"或工厂/提供程序机制来移动匹配运行时特定值并根据命名约定返回具体类型的逻辑?还是有其他想法可以实现这一点?
更新:我正在使用以下模式进行数据库访问:https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=92
因此,对于我的每种类型的查询,我都有一个IQueryHandler<,>的实现。
IQueryHandler<GetDocInfo, DocInfo>
IQueryHandler<GetFileInfo, FileInfo>
IQueryHandler<GetOrderInfo, OrderInfo>
IQueryHandler<GetMessageInfo, MessageInfo>
我的确切问题是,我在不同的客户端中对某些表格有不同的模式,因此我必须根据URL中的路由配置覆盖某些客户端的实现。
public class defaultschemaGetMessageQueryHandler : IQueryHandler<GetMessageInfo, MessageInfo>
public class client1schemaGetMessageQueryHandler : IQueryHandler<GetMessageInfo, MessageInfo>
public class client2schemaGetMessageQueryHandler : IQueryHandler<GetMessageInfo, MessageInfo>
我对它感兴趣的另一个地方是,覆盖特定查询实现以从不同的数据存储中提取:API或NoSQL。
更新2 最终更新。因此,我采用下面的代码并进行修改,从命名方案移动到基于属性的方案,因为我不希望每个不同默认类型的IQueryable都被命名为“QueryHandler”。
将此更改为:
string route = serviceType.Name.Substring(0, indexOfSuffix);
到这个:
string route = System.ComponentModel.TypeDescriptor
.GetAttributes(serviceType)
.OfType<QueryImplementation>()
.Single()
.Id;
我添加了以下属性,用于装饰我的IQueryHandlers
[System.AttributeUsage(System.AttributeTargets.Class |
System.AttributeTargets.Struct)
]
public class QueryImplementation : System.Attribute
{
public string Id { get { return id; } }
private string id;
public QueryImplementation(string id)
{
this.id = id;
}
}
使用方式如下:
[QueryImplementation("Custom")]
public class CustomDocQueryHandler : IQueryHandler<GetDocInfo, DocInfo>
然后我只需要对我的“默认值”执行相同的操作,以通过属性而不是名称进行获取。