我可以仅将自定义属性限制为void方法吗?

时间:2015-05-08 14:31:34

标签: c# attributes custom-attributes postsharp

我有一个自定义属性,我想将其限制为返回类型为void的方法。

我知道我可以限制使用[AttributeUsage(AttributeTargets.Method)]的方法,但似乎没有办法限制返回类型或方法签名的任何其他方面。

[System.Diagnostics.Conditional]属性正是​​我想要的那种限制。将其添加到非void方法会导致编译器错误:

  

Conditional属性在'(SomeMethod)'上无效,因为它的返回类型不是空的

和IntelliSense说:

  

属性'System.Diagnostics.ConditionalAttribute'仅对有效   具有'void'返回类型的属性类或方法。

如果我F12到ConditionalAttribute我看到它装饰有以下属性:

  

[序列化]
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple = true)]
  [标记有ComVisible特性(真)]

其中没有任何关于返回类型的内容。

如何为Conditional属性完成,我可以为自定义属性执行相同操作吗?

2 个答案:

答案 0 :(得分:4)

在我的特定情况下,由于我使用的是PostSharp,因此有一个解决方案。

我的自定义属性继承自PostSharp.Aspects.MethodInterceptionAspect(继承自Attribute),具有可覆盖的CompileTimeValidate(MethodBase method)方法。

这允许在构建期间发出编译器错误:

public override bool CompileTimeValidate(MethodBase method)
{
    Debug.Assert(method is MethodInfo);
    var methodInfo = (MethodInfo)method;

    if (methodInfo.ReturnType != typeof(void))
    {
        Message.Write(
            method, SeverityType.Error, "CX0001",
            "The Foo attribute is not valid on '{0}' because its return type is not void",
            method.Name);

        return false;
    }

    return true;
}

答案 1 :(得分:3)

大多数属性只是附加到类的元数据,可以在运行时检查。但是,编译器使用某些属性。例如,System.ObsoleteAttribute可用于让编译器在使用方法,类等时发出错误或警告。 System.Diagnostics.ConditionalAttribute是编译器使用的属性的另一个示例。因此,编译器本身可以自由地对其使用施加规则,这些规则不能应用于其他属性(例如仅使用void方法)。

不幸的是,目前,通过自定义属性不可能影响编译器。随着Rosalyn用C#编写,然后打开方式让编译器在属性中运行代码作为编译阶段的一部分。如果实现了限制属性为void方法,则可以使用此功能。