检查传递给 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
{
}
当我将表示 MyAttribute
的 AttributeData
对象传递给上面定义的 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:
时的值
如您所见,argumentValue
是 76
,argumentValueString
是 "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;
}
当我将表示 MyAttribute
的 AttributeData
对象传递给方法时,这个新实现 returns true
(完全符合我的要求)。
我想检查属性类型是否应用了 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
{
}
当我将表示 MyAttribute
的 AttributeData
对象传递给上面定义的 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:
如您所见,argumentValue
是 76
,argumentValueString
是 "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;
}
当我将表示 MyAttribute
的 AttributeData
对象传递给方法时,这个新实现 returns true
(完全符合我的要求)。