【发布时间】:2014-06-05 21:03:45
【问题描述】:
我有一系列形式的 WCF 服务
[WCFEndpoint]
public class MyWCFEndpoint : WCFSvcBase, IMyWCFEndpoint
{
}
其中 WCFEndpoint 是 PostSharp OnMethodBoundaryAspect:
[Serializable]
public class WCFEndpointAttribute : OnMethodBoundaryAspect
{
}
[WCFEndpoint] 的主要目的是通过覆盖 OnEntry 和 OnExit 以及其他诊断信息来提供有关 WCF 调用的持续时间信息。
问题是开发人员偶尔会忘记将 [WCFEndpoint] 添加到新的 WCF 服务(编辑:其他进行代码审查的开发人员忘记提及它!)。
我的目标是保证从 WCFSvcBase 派生的每个类都装饰有 [WCFEndpoint] 属性。我的计划是编写一个自动化 (NUnit) 测试来查找从 WCFSvcBase 派生的所有类,然后查看自定义属性并确认 WCFEndpointAttribute 在该集合中(为便于阅读而简化):
Assembly assm = Assembly.GetAssembly(typeof(ReferenceSvc));
Type[] types = assm.GetTypes();
IEnumerable<Type> serviceTypes =
types.Where(type => type.IsSubclassOf(typeof(WCFSvcBase)) && !type.IsAbstract );
foreach (Type serviceType in serviceTypes)
{
if (!serviceType.GetCustomAttributes(true).Any(x => x.GetType() == typeof(WCFEndpointAttribute)))
{
Assert.Fail( "Found an incorrectly decorated svc!" )
}
}
我的问题是 WCFEndpointAttribute 没有出现在 GetCustomAttributes(true) 中 - 即使它派生自 System.Attribute。我也通过查看 .Net Reflector 中的程序集确认了这一点。
理想情况下,由于 OnMethodBoundaryAspect 派生自 Attribute,我想以某种方式将 [WCFEndpoint](或类似的自定义属性)“打印”到最终编译的程序集元数据中。这是迄今为止概念上最简单的答案:它在代码中可见,并且在程序集元数据中可见。 有没有办法做到这一点?
我发现this article 描述了自动注入自定义属性的 TypeLevelAspect 的使用,如果我可以从 TypeLevelAspect 和 OnMethodBoundaryAspect 派生 WCFEndpointAttribute(是的,我知道为什么我不能这样做),这将非常有用。 :)
我考虑过的其他解决方法是:
1) 执行代码解析以确认 [WCFEndpoint] 是“近”(上一行): WCFSvcBase。这在可维护性/鲁棒性方面存在明显问题。
2) 自动将 [WCFEndpoint] 附加到通过multicasting 从 WCFSvcBase 派生的所有类。我不喜欢这个,因为它掩盖了 PostSharp/attributes 在检查服务代码时发挥作用的细节,尽管如果没有更优雅的解决方案是可能的。
3) 创建一个 AssemblyLevelAspect 以在构建时输出具有 [WCFEndpoint] 属性的所有类的列表。然后,我可以将此静态列表与从 WCFBaseSvc 派生的反射生成的类列表进行比较。 AssemblyLevelAspect 详细信息here。
我还应该指出,我仅限于 PostSharp 的 Free/Express 版本。
【问题讨论】: