簡體   English   中英

從枚舉動態獲取char或int值

[英]Dynamically obtaining char or int values from enums

我正在為使用數據庫中的自定義架構的項目編寫DAL,該項目具有一些基本操作:選擇,插入,更新和刪除。 每個操作都有其對應的方法來接收對象,並且這些方法使用Reflection提取有關表和列的信息。

編寫更新操作時,我需要從屬性中提取一些Enum值(某些列在數據庫中具有char或int值,並且我正在使用Enums在系統內部映射它們)。 從這里開始我的問題:

我編寫了一個靜態方法來檢查每個屬性及其類型。 如果為Enum,則該方法必須發現Enum是否具有int或char值。 我知道可以將任何值強制轉換為int,但是我需要特定的char或int將此值保存在數據庫中。

我從SO的其他問題中嘗試了很多強制類型轉換,但是強制類型轉換不起作用或強制類型轉換引發異常。

我的方法是這樣的:

private IEnumerable<PropertyInfo> ExtractObjectProperties(Object object)
{
    return objeto.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
                               BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
}

protected IEnumerable<OracleParameter> ExtractNonKeyParameters(Object object)
{
    var assembly = Assembly.Load("GN.Portal.Metadata");

    foreach (var propertyInfo in ExtractObjectProperties(object).Where(p => !p.GetCustomAttributes(typeof(KeyAttribute), true).Any()))
    {
        var columnAttribute = (ColumnAttribute)propertyInfo.GetCustomAttributes(typeof(ColumnAttribute), true).FirstOrDefault();
        if (columnAttribute != null)
        {
            if (propertyInfo.PropertyType.Namespace != "GN.Portal.MetaData.Enums")
            {
                yield return new OracleParameter
                {
                    ParameterName = columnAttribute.Name,
                    Value = propertyInfo.GetValue(object, null)
                };
            }
            else
            {
                var value = (Enum)Enum.ToObject(assembly.GetType(propertyInfo.PropertyType.FullName), propertyInfo.GetValue(object, null));
                var type = EnumsResolver.Resolve(value.GetType());

                switch (type.Name.ToLower())
                {
                    case "char":
                        yield return new OracleParameter
                        {
                            ParameterName = columnAttribute.Name,
                            Value = /* cast 'value' (Enum) to char here */
                        };
                        break;
                    case "int":
                        yield return new OracleParameter
                        {
                            ParameterName = columnAttribute.Name,
                            Value = /* cast 'value' (Enum) to int here */
                        };
                        break;
                    default:
                        yield return new OracleParameter
                        {
                            ParameterName = columnAttribute.Name,
                            Value = value
                        };
                        break;
                }
            }
        }
    }
}

EnumsResolver在下面(這不是一個好的解決方案,但是我沒想到更好的東西):

using System;

namespace GN.Portal.MetaData.Enums
{
    public static class EnumsResolver
    {
        public static Type Resolve(Type type)
        {
            switch (type.Name)
            {
                case "MyEnum1":
                    return typeof (char);
                case "MyEnum2":
                    return typeof (int);
                case "MyEnum3":
                    return typeof (char);
                case "MyEnum4":
                    return typeof (char);
                case "MyEnum5":
                    return typeof (char);
                default:
                    return typeof (string);
            }
        }
    }
}

我該如何解決一個好的解決方案?

您可以使用Enum.GetUnderlyingType獲得enum的基礎類型。

使用Convert.ChangeType將其轉換為正確的類型。

還要注意的是Type.IsEnum ,它使您無需檢查名稱空間來確定類型是否為枚舉。

if (!propertyInfo.PropertyType.IsEnum)
{
    yield return new OracleParameter
    {
        ParameterName = columnAttribute.Name,
        Value = propertyInfo.GetValue(object, null)
    };
}
else
{
    var enumUnderlyingType = Enum.GetUnderlyingType(propertyInfo.PropertyType);
    var value = propertyInfo.GetValue(objeto, null);

    yield return new OracleParameter 
    {
        ParameterName = columnAttribute.Name,
        Value = Convert.ChangeType(value, enumUnderlyingType)
    };
}

應盡可能簡單:

public static Type Resolve(Type type)
{
    return Enum.GetUnderlyingType(type);
}

並且可以將cast更改為Convert.ChangeType調用:

else
{
    var value = (Enum)Enum.ToObject(assembly.GetType(propertyInfo.PropertyType.FullName), propertyInfo.GetValue(objeto, null));
    var type = EnumsResolver.Resolve(value.GetType());

    yield return new OracleParameter
    {
        ParameterName = columnAttribute.Name,
        Value = Convert.ChangeType(value, type)
    };
}

而不是所有開關:

yield return new OracleParameter
{
    ParameterName = columnAttribute.Name,
    Value = Convert.ChangeType(value, EnumResolver.Resolve(value.GetType());
};

枚舉解析器:

using System;

namespace GN.Portal.MetaData.Enums
{
    public static class EnumsResolver
    {
        public static Dictionary<Type,List<Type> typeToType = new Dictionary<Type,List<Type>>()
        {
            {typeof(char),new List<Type>{typeof(MyEnum1),typeof(MyEnum3),typeof(MyEnum4),typeof(MyEnum5)}},
            {typeof(int),new List<Type>{typeof(MyEnum2)}}
        };
        public static Type Resolve(Type type)
        {
            IEnumerable<Type> types = typeToType.Where(x => x.Value.Contains(type)).Select(x => x.Key);
            return types.Any() ? types.First() : typeof(string);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM