gpt4 book ai didi

c# - 如何确定一个类是否在构建或运行时用 PostSharp 方面装饰

转载 作者:行者123 更新时间:2023-11-30 22:05:51 25 4
gpt4 key购买 nike

我有一系列 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 派生自属性,我想以某种方式将 [WCFEndpoint](或类似的自定义属性)“打印”到最终编译的程序集元数据中。这是迄今为止概念上最简单的答案:它在代码中可见,在程序集元数据中可见。 有办法做到这一点吗?

我找到了 this article描述了自动注入(inject)自定义属性的 TypeLevelAspect 的使用,如果我可以从 TypeLevelAspect 和 OnMethodBoundaryAspect 派生 WCFEndpointAttribute ,这将非常有用(是的,我知道为什么我不能这样做)。 :)

我考虑过的其他解决方法是:

1) 执行代码解析以确认 [WCFEndpoint] 是“附近”(上面一行): WCFSvcBase。这在可维护性/稳健性方面存在明显的问题。

2) 通过 multicasting 自动将 [WCFEndpoint] 附加到从 WCFSvcBase 派生的所有类.我不喜欢这个,因为它掩盖了检查服务代码时 PostSharp/属性正在发挥作用的细节,尽管如果没有更优雅的解决方案,这是可能的。

3) 创建一个 AssemblyLevelAspect 以在构建时吐出具有 [WCFEndpoint] 属性的所有类的列表。然后,我可以将此静态列表与派生自 WCFBaseSvc 的类的反射生成列表进行比较。 AssemblyLevelAspect 详细信息 here .

我还应该指出,我仅限于 PostSharp 的免费/快速版。

最佳答案

我能够通过在方面定义中包含 PersistMetadata=true 来保留 WCFEndpoint 属性:

[Serializable]
[MulticastAttributeUsage(PersistMetaData = true)]
public class WCFEndpointAttribute : OnMethodBoundaryAspect
{
}

查看 .Net Reflector 中的元数据,我现在看到了

public class MyWCFEndpoint : WCFSvcBase, IMyWCFEndpoint
{
[WCFEndpoint]
static MyWCFEndpoint();

[WCFEndpoint]
public MyWCFEndpoint();

[WCFEndpoint]
public void EndpointFn1();

[WCFEndpoint]
public void EndpointFn2();
}

元数据中存储的WCFEndpointAttribute的定义是

public WCFEndpointAttribute()
{

}

从这里开始,我可以将我的验证规则调整为“如果从 WCFSvcBase 派生的类上至少有一个方法具有 WCFEndpoint 属性,则验证通过;否则失败。”

验证码变为

IEnumerable<Type> serviceTypes =
types.Where(type => type.IsSubclassOf(typeof(WCFSvcBase))
&& !type.IsAbstract );

foreach (Type serviceType in serviceTypes)
{
var members = serviceType.GetMembers();
if (!members.Exists( member => member.GetCustomAttributes(true).Any(attrib => attrib.GetType() == typeof(WCFEndpointAttribute))))
{
Assert.Fail( "Found an incorrectly decorated svc!" )
}
}

我当然没有意识到 OnMethodBoundaryAspect 正在向所有成员(私有(private)、公共(public)、静态等)进行多播,尽管事后看来这确实是有道理的。我最终可能会创建一个复合方面,其中包括类的 TypeLevelAspect 和成员的 OnMethodBoundaryEntry 方面(这样我就可以直接查找所有类),但是这个元数据足以解决我眼前的问题。

感谢大家帮助缩小范围!

关于c# - 如何确定一个类是否在构建或运行时用 PostSharp 方面装饰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24070246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com