简体   繁体   English

从枚举获取属性,仅了解PropertyInfo

[英]Get attribute from Enum knowing only the PropertyInfo

What I have: 我有的:

I have a class where many of the properties use a specific type of attribute. 我有一个类,其中许多属性使用特定类型的属性。 This class also contains a property which is a nullable enum, and each value of the enum may also be decorated with the same attribute. 此类还包含一个可为空的枚举的属性,并且枚举的每个值也可以使用相同的属性修饰。 For example: 例如:

// My basic class
public class Upgrade
{
    [Abbreviation("name")]
    public int string Name { get; set; }

    [Abbreviation("opt")]
    public bool Optional { get; set; } = true;

    [Abbreviation("type")]
    public UpgradeType? TypeOfUpgrade { get; set; } = null;
}

// My basic enum
public enum UpgradeType
{
    [Abbreviation("fl")]
    Full, 

    [Abbreviation("prt")]
    Partial
}

// My basic attribute
public class AbbreviationAttribute: Attribute 
{
    public string Value{ get; private set; }

    public AbbreviationAttribute(string value)
    {
        Value = value;
    }
}

What I'm trying to do: 我正在尝试做的是:

I'm trying to get the name of each property and it's value. 我正在尝试获取每个属性的名称及其值。 However, if the property is decorated with the AbbreviationAttribute , the value from the attribute should be used instead. 但是,如果该属性用AbbreviationAttribute装饰,则应改用该属性的值。 Likewise, if the property is any type of enum, the value should be taken from the enum's AbbreviationAttribute , if it has one. 同样,如果属性是任何类型的枚举,则该值应从枚举的AbbreviationAttribute (如果它具有一个)。

So for an object such as this: 因此,对于这样的对象:

Upgrade upgrade = new Upgrade 
{
    Name = "First Upgrade",
    Optional = false,
    TypeOfUpgrade = UpgradeType.Full
};

I'd like to output the string: 我想输出字符串:

name=First Upgrade;opt=false;type=fl 名称=第一次升级; opt = false;类型= fl

How can I achieve this? 我该如何实现?

What I've tried: 我尝试过的

I've can get the attribute from the property, however I'm not sure how to access it from the enum property. 我可以从属性中获取属性,但是我不确定如何从枚举属性中访问它。 So in the above example, I can get the AbbreviationAttribute from the TypeOfUpgrade property, but since it's an enum, I need to get the AbbreviationAttribute from it's value. 因此,在上面的示例中,我可以从TypeOfUpgrade属性获取AbbreviationAttribute ,但是由于它是一个枚举,因此需要从其值获取AbbreviationAttribute

string values = string.Empty;
// foreach property
foreach(PropertyInfo pi in this.GetType().GetProperties())
{
    // get the attribute from the property, if it exists
    AbbreviationAttribute attr = pi.GetCustomAttribute<AbbreviationAttribute>();

    if (attr != null)
    {
        //append the value from the attribute, instead of the property name
        values += $"{attr.Value}=";

        // if property is an enum (nullable or otherwise)
        if (pi.PropertyType.IsEnum || pi.PropertyType.IsNullableEnum())
        {
            // get the type of enum
            Type type = Nullable.GetUnderlyingType(pi.PropertyType);
            if (type == null)
            {
                type = pi.PropertyType;
            }

            // --------------------------
            // Now I have the type of enum, and the value from the PropertyInfo,
            // how can I access the AbbreviationAttribute that's on the enum's value? 

        }
    }
}

// helper method
public static bool IsNullableEnum(this Type t)
{
    Type u = Nullable.GetUnderlyingType(t);
    return (u != null) && u.IsEnum;
}

An enum value is a static field of the enum type. 枚举值是枚举类型的静态字段。

So once you have an enum value, you get the Type for the enum type, get the field info for the enum value, and get the attribute from the member info. 所以,一旦你有一个枚举值,你得到的Type为枚举类型,获取枚举值的字段信息,并从会员信息的属性。

public static TAttributeType GetEnumValueAttribute<TAttributeType>(Enum val) 
    where TAttributeType : Attribute
{
    if (val == null)
    {
        return null;
    }

    return 
        val.GetType().
        GetMember(val.ToString())?.
        FirstOrDefault()?.
        GetCustomAttribute<TAttributeType>();
}

And in your loop: 在你的循环中:

foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
    // get the attribute from the property, if it exists
    AbbreviationAttribute attr = pi.GetCustomAttribute<AbbreviationAttribute>();

    if (attr != null)
    {
        //append the value from the attribute, instead of the property name
        values += $"{attr.Value}=";

        // if property is an enum (nullable or otherwise)
        if (pi.PropertyType.IsEnum || pi.PropertyType.IsNullableEnum())
        {
            values += $"{GetEnumValueAttribute<AbbreviationAttribute>((Enum)pi.GetValue(obj))?.Value};";
        }
        else
        {
            values += $"{pi.GetValue(obj)};";
        }
    }
}

You're really asking a duplicate of this question . 您真的是在问这个问题的副本。 I copied his code, but modernized it a bit. 我复制了他的代码,但进行了一些现代化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM