我正在为在数据库中使用自定义架构的项目编写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);
}
}
}
}
如何通过良好的解决方案解决这些演员表?
答案 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);
}
}
}