【发布时间】:2011-06-07 14:03:57
【问题描述】:
我们有一个抽象类,它是我们通过 WCF 服务发送的许多不同请求的基础。每次我们添加一个新请求时,我们都必须记住将[KnownType] 属性添加到这个基类,这是一个丑陋的令人发指的黑客攻击。
有没有办法告诉DataContractSerializer 将此抽象类型的所有派生视为KnownType?
【问题讨论】:
标签: .net wcf abstract-class known-types
我们有一个抽象类,它是我们通过 WCF 服务发送的许多不同请求的基础。每次我们添加一个新请求时,我们都必须记住将[KnownType] 属性添加到这个基类,这是一个丑陋的令人发指的黑客攻击。
有没有办法告诉DataContractSerializer 将此抽象类型的所有派生视为KnownType?
【问题讨论】:
标签: .net wcf abstract-class known-types
我在 WCF 服务中遇到了同样的问题,并做了以下“不那么令人发指”的黑客攻击来解决已知的类型限制。我概述只是为了显示替代选项,由您决定是否更好。
在服务启动时,通过反射加载您想要公开的类型。例如。如果所有暴露于 WCF 的实体都派生自一个公共抽象基(或更多),则从它们应该位于的程序集中加载所有类型。出于性能原因静态缓存这些类型。
创建一个返回上述缓存类型的静态方法,具有以下签名:
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
使用以下属性标记 WCF 接口
[ServiceKnownType("GetKnownTypes", typeof(StaticClassThatCachesTypes))]
这应该让您自动公开所有从您选择的基类派生或将派生的类型,只要未来的开发人员将它们放在正确的组装。
【讨论】:
除了 Dan C. 给出的选项之外,另一种选择是切换到 NetDataContractSerializer - 它不需要已知类型声明,因为它与确切的合约实现紧密耦合,因此您需要共享包含客户端和服务器之间类型的程序集 - 在这种情况下您肯定会失去互操作性。有一些关于这样做的帖子(我经常在 google/bing 结果中看到this one 弹出)。
【讨论】:
Here 是使用 PostSharp 执行此操作的示例。往帖子底部看。
【讨论】:
This 是使用Fody/Mono.Cecil 通过 IL Weaving 实现此目的的一个示例。
基本上,这是一个 Fody 扩展,在构建期间使用 IL Weaving 注入 KnownTypeAttributes。
在构建管道期间,扩展定位所有标有 KnowsDeriveTypes 属性的基类(扩展的一部分),并将 KnownTypeAttribute 添加到所有派生类(不是 必须直接)来自上述基类之一(使用 KnowsDeriveTyepsAttribute)。
【讨论】: