从枚举中动态获取char或int值

时间:2014-02-07 18:43:58

标签: c# enums

我正在为在数据库中使用自定义架构的项目编写DAL,其中包含一些基本操作:选择,插入,更新和删除。每个操作都有其接收Object的相应方法,这些方法使用Reflection提取有关表和列的信息。

编写 update 操作,我需要从属性中提取一些Enum值(某些列在数据库中有char或int值,我使用Enums将它们映射到系统内)。这开始我的问题:

我编写了一个静态方法来检查每个属性及其类型。如果是枚举,则该方法必须发现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);
            }
        }
    }
}

如何通过良好的解决方案解决这些演员表?

3 个答案:

答案 0 :(得分:2)

您可以使用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)
    };
}

答案 1 :(得分:1)

应该如此简单:

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

投射可以更改为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)
    };
}

答案 2 :(得分:1)

而不是所有开关:

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

Enum Resolver:

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