c#自定义属性可以在编译时求值吗?

本文关键字:编译 自定义属性 | 更新日期: 2023-09-27 18:16:01

我有以下自定义属性:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed public class CLSASafeAttribute : Attribute
{
    public Boolean CLSSafe { get; set; }
    public CLSASafeAttribute(Boolean safe)
    {
        CLSSafe = safe;
    }
}

和以下枚举部分:

public enum BaseTypes
{
    /// <summary>
    /// Base class.
    /// </summary>
    [CLSASafe(true)]
    Object = 0,
    /// <summary>
    /// True / false.
    /// </summary>
    [CLSASafe(true)]
    Boolean,
    /// <summary>
    /// Signed 8 bit integer.
    /// </summary>
    [CLSASafe(false)]
    Int8
}

我现在希望能够为每个enum创建一个唯一的类,并能够通过查看正在实现的类型将其标记为CLSSafe。我有以下的,这显然是不正确的,但说明了我的意图:

[CLSASafe((Boolean)typeof(BaseTypes.Object).GetCustomAttributes(typeof(BaseTypes.Object), false))]
sealed public class BaseObject : Field
{
    public Object Value;
}

是否有办法做到这一点(除了手动标记签名)?

c#自定义属性可以在编译时求值吗?

我建议你这样定义你的属性:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed public class CLSASafeAttribute : Attribute {
    public CLSASafeAttribute(Boolean safe) {
        CLSSafe = safe;
    }
    public CLSASafeAttribute(BaseTypes type) {
        CLSSafe = IsCLSSafe(type);
    }
    public Boolean CLSSafe {
        get;
        private set;
    }
    public static bool IsCLSSafe(BaseTypes type) {
        var fieldInfo = typeof(BaseTypes).GetField(typeof(BaseTypes).GetEnumName(type));
        var attributes = fieldInfo.GetCustomAttributes(typeof(CLSASafeAttribute), false);
        return (attributes.Length > 0) && ((CLSASafeAttribute)attributes[0]).CLSSafe;
    }
}

然后,可以使用以下声明:

class Foo {
    [CLSASafe(BaseTypes.Object)] // CLSSafe = true
    object someField1;
    [CLSASafe(BaseTypes.Boolean)] // CLSSafe = true
    bool someField2;
    [CLSASafe(BaseTypes.Int8)] // CLSSafe = false
    byte someField3;
}

或者,无论如何,确定特定字段是否安全:

BaseTypes baseType = GetBaseType(...type of specific field ...);
bool isCLSSafe = CLSASafeAttribute.IsCLSSafe(baseType);