检查传递给 AttributeUsageAttribute 构造函数的参数

Checking the argument passed to the `AttributeUsageAttribute` constructor

我想检查属性类型是否应用了 AttributeUsage 属性 是否将 AttributeTargets.Class 传递给了 AttributeUsage构造函数。这是我为执行检查而编写的代码:

bool CheckSomeArbitraryConditionMet(AttributeData attributeData)
{
    AttributeData[] attributeUsages =
        attributeData.AttributeClass.GetAttributes().Where(
            a => a.AttributeClass.Name == "AttributeUsageAttribute").ToArray();

    if (attributeUsages.Any())
    {
        return
            attributeUsages.Any(
                a =>
                    a.ConstructorArguments.Any(constant => constant.Value != null && constant.Value.ToString().Contains("AttributeTargets.Class"))
                    || a.NamedArguments.Any(kvp => kvp.Value.ToString().Contains("AttributeTargets.Class")));
    }
    return true;
}

我有一个属性如下:

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Method)]
public class MyAttribute : System.Attribute
{
}

当我将表示 MyAttributeAttributeData 对象传递给上面定义的 CheckSomeArbitraryConditionMet(AttributeData data) 方法时,方法 returns false 而不是 true.

我在if (attributeUsages.Any())行下了断点,在Immediate Window行执行了如下代码:

var attribute = attributeUsages.Single();
Expression has been evaluated and has no value
var constructorArguments = attribute.ConstructorArguments;
Expression has been evaluated and has no value
var argument = constructorArguments.Single();
Expression has been evaluated and has no value
var argumentValue = argument.Value;
Expression has been evaluated and has no value
var argumentValueString = argumentValue.ToString();
Expression has been evaluated and has no value

这是我检查 Locals window:

时的值

如您所见,argumentValue76argumentValueString"76"。所以难怪 CheckSomeArbitraryConditionMet(AttributeData data) 方法 returns false!

如何检查 AttributeTargets.Class 是否传递给 AttributeUsage 构造函数?

我以 the Enum.TryParse() documentation 上的示例为灵感,将 CheckSomeArbitraryConditionMet(AttributeData data) 的实现修改为以下内容:

bool CheckSomeArbitraryConditionMet(AttributeData attributeData)
{
    AttributeData[] attributeUsages =
        attributeData.AttributeClass.GetAttributes().Where(
            a => a.AttributeClass.Name == "AttributeUsageAttribute").ToArray();

    if (attributeUsages.Any())
    {
        return
            attributeUsages.Any(
                attributeUsage =>
                    attributeUsage.ConstructorArguments.Any(
                        arg =>
                        {
                            string argValue = arg.Value.ToString();

                            return
                                arg.Kind == TypedConstantKind.Enum
                                && arg.Type.Name == "AttributeTargets"
                                && Enum.TryParse(argValue, ignoreCase: false, out AttributeTargets parsedValue)
                                && parsedValue == AttributeTargets.Class | parsedValue.ToString().Split(',').Contains("Class");
                        }));
    }
    return true;
}

当我将表示 MyAttributeAttributeData 对象传递给方法时,这个新实现 returns true(完全符合我的要求)。