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

时间:2019-07-01 17:47:20

标签: c# attributes

我所拥有的:

我有一个类,其中许多属性使用特定类型的属性。此类还包含一个可为空的枚举的属性,并且枚举的每个值也可以使用相同的属性修饰。例如:

// 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;
    }
}

我正在尝试做的事情:

我正在尝试获取每个属性的名称及其值。但是,如果属性用AbbreviationAttribute装饰,则应改用属性中的值。同样,如果属性是任何类型的枚举,则该值应从枚举的AbbreviationAttribute(如果有)获取。

对于这样的对象:

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

我想输出字符串:

  

name =首次升级; opt = false; type = fl

我该如何实现?

我尝试过的事情:

我可以从属性中获取属性,但是我不确定如何从枚举属性中访问它。因此,在上面的示例中,我可以从AbbreviationAttribute属性中获取TypeOfUpgrade,但是由于它是一个枚举,因此我需要从其值中获取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;
}

1 个答案:

答案 0 :(得分:0)

枚举值是枚举类型的静态字段。

因此,一旦有了枚举值,就可以获取枚举类型的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>();
}

在您的循环中:

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)};";
        }
    }
}

您实际上是要复制this question。我复制了他的代码,但进行了一些现代化。