[英]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.