在多个成员上使用Postsharp Aspects而不进行多重转换

时间:2013-10-04 13:15:46

标签: c# postsharp

是否可以使用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实际将属性多播到所有成员呢?

1 个答案:

答案 0 :(得分:2)

您的自定义属性派生自Aspect类,而后者又来自MulticastAttribute - 这就是您获得多播行为的原因。

您可以做的是从System.Attribute派生并实现您需要的所有接口。在您的情况下,这将是IAspectProviderIValidableAnnotation

[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方法 - 此方法仅在执行多播后才运行,以确定是否为已应用属性的每个给定代码元素引入方面。