是否可以使用Postsharp属性,可以在不使用MulticastAttributeUsage的情况下应用于类,接口,属性,字段或方法,以便用户确切地确定应用哪些成员而无需对每个成员进行多重操作。< / p>
如果我使用MulticastAttributeUsage并在类上使用my属性,它会自动在我生成的IL中的所有属性,方法等上放置我的属性的新实例。
如果我不使用它,它将无法编译,因为它抱怨我需要使用它(我从Aspect类派生)。
这是我的情景:
我正在创建一个新的Serialization属性,所以我希望能够这样做:
[Serialise(ApplyToProperty="Test2", Name="Blah2")]
public class MyClass {
[Serialise(Name="Blah1")]
public string Test1 { get; set; }
public bool Test2 { get; set; }
}
当我在运行时使用MulticastAttributeUsage反映时,我在Test1上获得了两个Serialise属性。当我看到生成的IL时,它显示了这个:
[Serialise(ApplyToProperty = "Test2", Name = "Blah2")]
public class Test {
[Serialise(ApplyToProperty = "Test2", Name = "Blah2"), Serialise(Name = "Blah")]
public string Test1 { get; set; }
[Serialise(ApplyToProperty = "Test2", Name = "Blah2")]
public bool Test2 { get; set; }
}
我可能不会使用Postsharp并且运行时的反射将完全符合我的需要,但我需要使用Postsharp来介绍另一个方面。我的SerialiseAttribute代码是这样的:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Property | AttributeTargets.Field)]
[MulticastAttributeUsage(MulticastTargets.Class | MulticastTargets.Interface | MulticastTargets.Property | MulticastTargets.Field, AllowMultiple = true, PersistMetaData = true, Inheritance = MulticastInheritance.None)]
public class SerialiseAttribute : Aspect, IAspectProvider {
public string ApplyToProperty { get; set; }
public string Name { get; set; }
public override bool CompileTimeValidate(object target) {
return false;
}
IEnumerable<AspectInstance> IAspectProvider.ProvideAspects(object targetElement) {
// Code that introduces a different attribute
}
}
另请注意,我从CompileTimeValidate返回false的事实似乎对生成的IL没有任何影响,看起来“无声失败”并不意味着“不要将属性应用于它”。那么如何防止Postsharp实际将属性多播到所有成员呢?
答案 0 :(得分:2)
您的自定义属性派生自Aspect
类,而后者又来自MulticastAttribute
- 这就是您获得多播行为的原因。
您可以做的是从System.Attribute
派生并实现您需要的所有接口。在您的情况下,这将是IAspectProvider
和IValidableAnnotation
。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Property | AttributeTargets.Field)]
public class Serialise : Attribute, IAspectProvider, IValidableAnnotation
{
public string ApplyToProperty { get; set; }
public string Name { get; set; }
public bool CompileTimeValidate(object target)
{
return false;
}
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
// Code that introduces a different attribute
}
}
对于CompileTimeValidate
方法 - 此方法仅在执行多播后才运行,以确定是否为已应用属性的每个给定代码元素引入方面。