我有一个WCF服务,其中包含以下操作 Contract :
[OperationContract]
Response SearchEntities(Query query);
此操作采用包含指定实体的请求,如下所示:
[DataContract]
public class Query
{
[DataMember]
public string SearchTerm { get; set; }
[DataMember]
public string Entity { get; set; }
[DataMember]
public bool ExactMatch { get; set; }
}
根据 Entity
属性中包含的值,在此响应中填充以下属性:
[DataContract]
public class Response
{
[DataMember]
public List<Asset> Assets { get; set; }
[DataMember]
public List<Stage> Stages { get; set; }
[DataMember]
public List<Sector> Sectors { get; set; }
}
可怕的设计,我知道!然而 . 我使用Autofac.Wcf作为我的服务工厂来注入依赖项 . 通常我会使用一个通用的接口和泛型来确定一个基于 Entity
值的服务,如下所示:
public interface IEntitySearch<T>
{
Response Search(Query query);
}
上面的接口将为响应中的每个列表提供多个实现 . 使用诸如服务位置之类的设计模式,我可以确定使用哪个服务(所有服务都继承自 IEntitySearch<T>
,类似于:
public IEntitySearch ResolveSearcher(Query query)
{
switch(query.Entity)
{
case "Assets":
return _container.Resolve<AssetSearch>();
case "Stages":
return _container.Resolve<StageSearch>();
default:
throw new NotSupportedException();
}
}
虽然这有效,但更优雅的解决方案(我相信)将根据请求中包含的数据,针对此特定操作的每个请求自定义Autofac容器 .
IE:在WCF管道将请求发送到服务实现之前,是否可以检查请求数据并自定义容器如何解析依赖项 . 这样我就可以避免在服务层中暴露依赖项解析 .
这可能吗?
如果除了Autofac之外的另一个DI库有解决方案,我将很乐意改变我们的DI框架 .
谢谢 .
2 回答
我没有亲自试过这个,但我认为你可以采取的方向是:
使用OperationContext.Current获取当前请求消息数据 .
指定自定义IServiceImplementationDataProvider for Autofac,告知Autofac要为该请求托管哪个WCF接口 .
对服务实现使用lambda注册,以根据
OperationContext.Current
切换后备服务 .您可以通过查看DefaultServiceImplementationProvider看到
IServiceImplementationDataProvider
的两个示例 - 默认情况下在Autofac WCF托管中工作的那个 . 和MultitenantServiceImplementationDataProvider,这更多关于生成代理以启用多租户WCF托管 .虽然这些都不使用
OperationContext.Current
来确定实际的支持服务,但您可以 Build 在以下思路上:查看Autofac.Multitenant.Wcf实现 . 您可以按原样使用它 . 实例数据提供者的要点是WCF grab 了托管服务的具体类型,如果您尝试从其下面交换类型,则会出现错误 . 多租户支持通过创建代理类型来欺骗WCF,您的实现类型可以在代理下交换出来 . 请注意
MultitenantServiceImplementationDataProvider
仅仅是关于该代理的't actually tie anything to a tenant or tenant ID; it' .在
.svc
文件中指定服务接口而不是任何单独的具体实现,因为您将交换实现 .使用lambda注册来确定您的实现 .
确保您的服务是
InstanceContextMode.PerCall
,以确保根据请求换出内容 .注册可能如下所示:
WCF上的Autofac WCF和Autofac Multitenant部分也可能有所帮助 .
在我看来,你正试图将你的问题转移到另一个地方 . 为什么根据低级别WCF的请求做出决策比切换
SearchEntities
方法更好?这更糟糕;-)我会考虑使用
IEntitySearch
工厂/提供商e.q.IEntitySearchProvider
(它不是那么好但总是如此) .要么
同