简体   繁体   English

如何使用非泛型类型获取枚举的默认值?

[英]How do I get the default value of an Enum using a non-generic Type?

I have a method that iterates through an object's properties and sets the values to their type's default values. 我有一个方法可以迭代对象的属性,并将值设置为其类型的默认值。 Some properties are enums. 一些属性是枚举。 I have another function that gets the default value of the enum (not 0), but it requires passing the enum type which is not known in the current method. 我有另一个函数,它获取枚举的默认值(不是0),但是它需要传递当前方法未知的枚举类型。

    [DefaultValue(Red)]
    public enum Colors
    {
        Red = 1,
        green = 2
    }

    // In another class
    public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
    {
        Type t = typeof(TEnum);
        DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
        if (attributes != null && attributes.Length > 0)
        {
        return (TEnum)attributes[0].Value;
        }
        else
        {
        return default(TEnum);
        }
    }


    public static void ClearObject<T>(object obj)
    {
        obj = (T)obj;

        PropertyInfo[] props = obj.GetType().GetProperties();

        string propName = "";

        try
        {
        foreach (PropertyInfo pi in props)
        {
            propName = pi.Name;

            Type t = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType;
            if (t.IsEnum)
            {
            //  This works
            //  var val = EnumFunctions.GetDefaultValue<Colors>();

            // The error is here
            var val = EnumFunctions.GetDefaultValue<t>();
            //                                     ^^^

            pi.SetValue(obj, val);
            }
            // In case of nullable value types int,datetime, etc - set null  
            else if (Nullable.GetUnderlyingType(pi.PropertyType) != null)
            pi.SetValue(obj, null);
            else
            pi.SetValue(obj, null, null);
        }
        }
        catch (Exception e)
        {
        string msg = $"Error for {propName}: {e.Message}";
        throw new Exception(msg);
        }
    }

I've tried typeof(t) , t.GetType() . 我已经尝试过typeof(t)t.GetType()

I want the default value for a Colors enum property to be Red. 我希望Colors枚举属性的默认值为Red。 The line causing the error is 导致错误的行是

var val = EnumFunctions.GetDefaultValue<t>();
Error   CS0118  't' is a variable but is used like a type

You don't need generics here 您在这里不需要泛型

public static object GetDefaultValue(Type type)
{
    DefaultValueAttribute[] attributes = (DefaultValueAttribute[])type.GetCustomAttributes(typeof(DefaultValueAttribute), false);
    if (attributes != null && attributes.Length > 0)
    {
        return attributes[0].Value;
    }
    else
    {
        return null;
    }
}

And then you use it like this 然后像这样使用它

 var val = EnumFunctions.GetDefaultValue(t);
 if(val != null)
     pi.SetValue(obj, val);

Source of your confusion: 您的困惑之源:

Generally speaking, generics are not runtime construct, they're compile-time construct, so you can't use them in reflection, because reflection works at run time. 一般来说,泛型不是运行时构造,它们是编译时构造,因此您不能在反射中使用它们,因为反射在运行时起作用。

您也可以像这样通过反射调用该方法:

typeof(EnumFunctions).GetMethod("GetDefaultValue").MakeGenericMethod(t).Invoke(null, null);

Per my comment above (thought I could post code). 根据我上面的评论(我可以发布代码)。 I also wanted to ensure that enums were instantiated to a valid value. 我还想确保将枚举实例化为有效值。 Some enums do not have a 0 so the default of numeric types wouldn't work. 某些枚举没有0,因此默认的数字类型不起作用。

public MyClass() 
{
    // Sets default property values for all but dates
    Basefunctions.Clear<InternalExaminer>(this);

    // Sets default values by [DefalutValue()] tag.
    foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(this))
    {
        pd.ResetValue(this);
    }

    // Sets date properties to current date.
    Basefunctions.SetDates<MyClass>(this);
}

public static class Basefunctions
{
    public static void SetDates<T>(object obj)
    {
        string propName = "";

        try
        {
            obj = (T)obj;

            PropertyInfo[] props = obj.GetType().GetProperties()
                           .Where(p => p.PropertyType == typeof(DateTime)).ToArray();
            if (props != null)
            {
                DateTime date = DateTime.Now;
                foreach (PropertyInfo pi in props)
                {
                    propName = pi.Name;
                    if (Nullable.GetUnderlyingType(pi.PropertyType) == null)
                        pi.SetValue(obj, date);
                }
            }
        }
        catch (Exception e)
        {
            throw new Exception($"Could not set date for {propName}.\n{e.Message}");
        }
    }

    public static void Clear<T>(object obj)
    {
        obj = (T)obj;

        PropertyInfo[] props = obj.GetType().GetProperties();

        string propName = "";

        try
        {
            foreach (PropertyInfo pi in props)
            {
                propName = pi.Name;

                Type t = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType;

                if (Nullable.GetUnderlyingType(pi.PropertyType) != null)
                    pi.SetValue(obj, null);
                else
                {
                    var val = GetDefaultVal(t);
                    if (t.IsEnum)
                    {
                        // In case enum does not have a 0
                        if (!Enum.IsDefined(t, val))
                            val = EnumMin(pi.PropertyType);
                    }
                    pi.SetValue(obj, val);
                }
            }
        }
        catch (Exception e)
        {
            string msg = $"Error for {propName}: {e.Message}";
            throw new Exception(msg);
        }
    }

    private static object GetDefaultVal(Type type)
    {
        DefaultValueAttribute att = (DefaultValueAttribute)type.GetCustomAttribute(typeof(DefaultValueAttribute));

        if (att != null)
            return att.Value;
        else
            return type.IsValueType ? Activator.CreateInstance(type) : null;
    }

    private static object EnumMin(Type t)
    {
        Array x = Enum.GetValues(t);
        var ret = x.GetValue(0);
        return ret;
    }

    private static object EnumMax(Type t)
    {
        Array x = Enum.GetValues(t);
        var ret = x.GetValue(x.Length - 1);
        return ret;
    }
}

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

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