我正在使用命令处理程序模式并与ninject.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>().ToMethod( context => HttpContext.Current.Request.RequestContext.RouteData.Values["type"].ToString().ToLower() == "api" ? (IQueryHandler )new apiHandler() : (IQueryHandler )new defaultHandler() )
上面的问题是我需要为我的每一个IQueryHandler <,>泛型类型编写这个代码.另外,对于我想要全局应用的每个装饰器(如顶部示例),我将不得不修改每个绑定并添加它,使代码加倍或三倍.
我希望完成的是使用类似下面的内容.我已经实现了一个类/接口来返回自定义的Route数据值.这会运行,但它会抛出异常,因为在运行时HttpContext.Current为null.我在想,因为它不能在运行时解析每个请求.
kernel.Bind().To ().InRequestScope(); kernel.Bind(x => x .FromThisAssembly() .SelectAllClasses() .InheritedFrom(typeof(IQueryHandler<,>)) .StartingWith(kernel.Get ().customRouteValue) // this isn't valid... .BindSingleInterface() .Configure(b => b.InRequestScope()) );
有没有办法使用"ToMethod"或工厂/提供程序机制来移动逻辑以匹配运行时特定值并根据命名约定返回具体类型?或者任何其他想法来实现这一目标?
更新:我使用以下模式进行数据库访问:https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id = 92
所以我对我的数据库的每种类型的查询都有一个IQueryHandler <,>的实现.
IQueryHandlerIQueryHandler IQueryHandler IQueryHandler
我的确切问题是我对客户端的某些表有不同的模式,因此我必须根据URL中的Route Config覆盖某些客户端的实现.
public class defaultschemaGetMessageQueryHandler : IQueryHandlerpublic class client1schemaGetMessageQueryHandler : IQueryHandler public class client2schemaGetMessageQueryHandler : IQueryHandler
我有兴趣使用它的另一个地方是覆盖一个特定的查询实现来从不同的数据存储区提取:API或NoSQL.
更新2 最后更新.所以我采用下面的代码并修改为从命名方案转移到基于属性,因为我不希望每个IQueryable都为每个不同的默认类型命名为"QueryHandler".
改变了这个:
string route = serviceType.Name.Substring(0, indexOfSuffix);
对此:
string route = System.ComponentModel.TypeDescriptor .GetAttributes(serviceType) .OfType() .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
然后只需要为我的"默认"做同样的事情来获取属性而不是名称.