2

是否有可能在不使用 MulticastAttributeUsage 的情况下将 Postsharp 属性应用于类、接口、属性、字段或方法,以便用户准确地决定应用它的成员,而无需对每个成员进行多播。

如果我使用 MulticastAttributeUsage 并在类上使用我的属性,它会自动将我的属性的新实例放在生成的 IL 中的所有属性、方法等上。

如果我不使用它,它将无法编译,因为它抱怨我需要使用它(我是从 Aspect 类派生的)。

这是我的场景:

我正在创建一个新的序列化属性,所以我希望能够做到这一点:

[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 将属性多播给所有成员呢?

4

1 回答 1

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

于 2013-10-07T08:49:13.933 回答