如何读取属性参数和值(class属性或方法属性)?

How to read attribute parameters and values (class attributes or method attributes)?

我想“读取”附加到 class 或方法的属性参数(例如 [MyAttribute("val1", "val2"]),或者想取回特定 class 或方法。这似乎不适用于所有情况。

当我试图实现它时,即

  1. Read parameters of an attribute, attached to a class. How? (see Question 1)
Parameters are the constructor parameters of the attribute, e.g.
public MyOwnAttribute(params object[] p).

  2. Get attibute object's properties, attached to a method. How? (see Question 2)
In the example attribute MyOwnAttribute, there are MyProperty1 and MyProperty2 defined. So if you apply it to
[MyOwnAttribute("World", "2")]
public void MyMethod2() {...},
how can I read them (the constructor assigns "World" to MyProperty1 and "2" to MyProperty1)?

  3. Read parameters of an attribute, attached to a method. Solved. Example: MyOwnAttribute.GetMethodAttributeValues<clsA>(nameof(clsA.MyMethod2))

  4. Get attribute object's properties, attached to a class. Solved. Example: MyOwnAttribute.GetClassAttributes(typeof(clsA)).MyProperty1

我注意到我无法为所有 4 个案例实现它,我无法为案例 1. 和案例 4 实现它。我为案例 2. 和 3. 编写的代码工作正常(我删除了它因为您现在对所有 4 个案例都有 Tobias 的回答)。 SO 侧边栏显示了一些有趣的链接(“相关”:Link 1, Link 2, Link 3),但我仍然无法将缺失的部分放在一起。

考虑以下自定义属性:

public class MyOwnAttribute : Attribute
{

    public string MyProperty1 { get; set; }
    public string MyProperty2 { get; set; }

    // simple case, to make explaining it easier
    public MyOwnAttribute(string p1 = null, string p2 = null)
    {
        MyProperty1 = p1?.ToString();
        MyProperty2 = p2?.ToString();
    }

}

或者我可以像这样定义属性:

    public string[] MyProperties { get; set; }

    // allows any number of properties in constructor
    public MyOwnAttribute(params object[] p)
    {
        MyProperties = p.Select(s => s.ToString()).ToArray();
    }

但我不知道你如何实现这个:

有没有人知道如何做到这一点?非常感谢。

编辑:

经过一些澄清后,我怀疑您想要的是:

public static class AttributeHelper {

    public static TAttribute GetClassAttribute<TTarget, TAttribute>() where TAttribute : Attribute
        => typeof(TTarget).GetAttribute<TAttribute>();

    public static object[] GetClassAttributeValues<TTarget, TAttribute>() where TAttribute : Attribute
        => typeof(TTarget).GetAttributeValues<TAttribute>();

    public static TAttribute GetMethodAttribute<TTarget, TAttribute>(string methodName) where TAttribute : Attribute
        => typeof(TTarget).GetMethod(methodName)?.GetAttribute<TAttribute>();

    public static object[] GetMethodAttributeValues<TTarget, TAttribute>(string methodName) where TAttribute : Attribute
        => typeof(TTarget).GetMethod(methodName)?.GetAttributeValues<TAttribute>();

    private static TAttribute GetAttribute<TAttribute>(this MemberInfo memberInfo) where TAttribute : Attribute
        => memberInfo?.GetCustomAttributes(true).OfType<TAttribute>().FirstOrDefault();

    private static object[] GetAttributeValues<TAttribute>(this MemberInfo memberInfo) where TAttribute : Attribute
        => memberInfo
            ?.GetCustomAttributesData()
            .FirstOrDefault(d => d.AttributeType == typeof(TAttribute))
            ?.ConstructorArguments
            .Select(argument => argument.Value)
            .SelectMany(a => a is ReadOnlyCollection<CustomAttributeTypedArgument> p ? p.Select(c => c.Value) : new[] { a })
            .ToArray();
}

这些方法现在都是静态的,AttributeHelper 不再派生自 Attribute,因为无论如何您都必须提供属性类型作为方法的参数。作为第二个参数,只需提供您期望属性的 class。

我花了一些时间重新组织代码,因为它对我来说很难阅读。也许它对您来说也更容易阅读。

调用示例:

AttributeHelper.GetClassAttributeValues<clsA, MyOwnAttribute>().Dump("1.");

AttributeHelper.GetMethodAttribute<clsA, 
                        MyOwnAttribute>(nameof(clsA.MyMethod2)).Dump("2.");

AttributeHelper.GetMethodAttributeValues<clsA,
                        MyOwnAttribute>(nameof(clsA.MyMethod2)).Dump("3.");

AttributeHelper.GetClassAttribute<clsA,MyOwnAttribute>().Dump("4.");

下面的旧答案:

我认为您想要实现的目标可以通过在 AttributeHelper 中使用 return 类型 string[] 的附加 protected abstract 方法来解决,这将使AttributeHelper也是抽象的,不过应该没问题。

您的派生属性将被迫实现这个新方法(如果它们本身不是抽象的)。实现必须 return 属性值的数组。

另一种方法可能是遍历属性类型的 PropertyInfos 并以这种方式读取属性。