在做项目的过程中发现有一种情况,就是实体类是不确定的,没办法写出对应的实体类cs文件,那么我们怎么来在数据传输过程中形成这么个动态的类
1,首先将从数据库查出的dataset或datatable转换成 List<Dictionary<string, string>>
/// <summary>
/// 将DataSet转换成List集合
/// </summary>
/// <param name="dataSet"></param>
/// <returns></returns>
public static List<Dictionary<string, string>> ConvertToIEnumerable(DataSet dataSet)
{
List<Dictionary<string, string>> list = null;
DataTable dt = dataSet.Tables[0];
if (dt.Rows.Count > 0)
{
list = new List<Dictionary<string, string>>();
foreach (DataRow dr in dt.Rows)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (DataColumn dc in dt.Columns)
{
dict.Add(dc.ColumnName, dr[dc.ColumnName].ToString());
}
list.Add(dict);
}
}
return list;
}
2.然后将List<Dictionary<string, string>> 转换成 IEnumerable<IDictionary>
public IEnumerable<IDictionary> GetEnumerable(List<Dictionary<string, string>> SourceList)
{
for (int i = 0; i < SourceList.Count; i++)
{
var dict = new Dictionary<string, string>();
dict = SourceList[i];
yield return dict;
}
}
3,将 IEnumerable<IDictionary> 转换成 List<object> 这时需要用到一个 DataSourceCreator 类
public static class DataSourceCreator
{
private static readonly Regex PropertNameRegex =
new Regex(@"^[A-Za-z]+[A-Za-z1-9_]*$", RegexOptions.Singleline);
public static List<object> ToDataSource(this IEnumerable<IDictionary> list)
{
IDictionary firstDict = null;
bool hasData = false;
foreach (IDictionary currentDict in list)
{
hasData = true;
firstDict = currentDict;
break;
}
if (!hasData)
{
return new List<object> { };
}
if (firstDict == null)
{
throw new ArgumentException("IDictionary entry cannot be null");
}
Type objectType = null;
TypeBuilder tb = GetTypeBuilder(list.GetHashCode());
ConstructorBuilder constructor =
tb.DefineDefaultConstructor(
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName);
foreach (DictionaryEntry pair in firstDict)
{
if (PropertNameRegex.IsMatch(Convert.ToString(pair.Key), 0))
{
CreateProperty(tb,
Convert.ToString(pair.Key),
pair.Value == null ?
typeof(object) :
pair.Value.GetType());
}
else
{
throw new ArgumentException(
@"Each key of IDictionary must be
alphanumeric and start with character.");
}
}
objectType = tb.CreateType();
return GenerateArray(objectType, list, firstDict);
}
private static List<object> GenerateArray(Type objectType, IEnumerable<IDictionary> list, IDictionary firstDict)
{
var itemsSource = new List<object>();
foreach (var currentDict in list)
{
if (currentDict == null)
{
throw new ArgumentException("IDictionary entry cannot be null");
}
object row = Activator.CreateInstance(objectType);
foreach (DictionaryEntry pair in firstDict)
{
if (currentDict.Contains(pair.Key))
{
PropertyInfo property =
objectType.GetProperty(Convert.ToString(pair.Key));
property.SetValue(
row,
Convert.ChangeType(
currentDict[pair.Key],
property.PropertyType,
null),
null);
}
}
itemsSource.Add(row);
}
return itemsSource;
}
private static TypeBuilder GetTypeBuilder(int code)
{
AssemblyName an = new AssemblyName("TempAssembly" + code);
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(
an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = moduleBuilder.DefineType("TempType" + code
, TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout
, typeof(object));
return tb;
}
private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName,
propertyType,
FieldAttributes.Private);
PropertyBuilder propertyBuilder =
tb.DefineProperty(
propertyName, PropertyAttributes.HasDefault, propertyType, null);
MethodBuilder getPropMthdBldr =
tb.DefineMethod("get_" + propertyName,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
propertyType, Type.EmptyTypes);
ILGenerator getIL = getPropMthdBldr.GetILGenerator();
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, fieldBuilder);
getIL.Emit(OpCodes.Ret);
MethodBuilder setPropMthdBldr =
tb.DefineMethod("set_" + propertyName,
MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.HideBySig,
null, new Type[] { propertyType });
ILGenerator setIL = setPropMthdBldr.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, fieldBuilder);
setIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getPropMthdBldr);
propertyBuilder.SetSetMethod(setPropMthdBldr);
}
}
4,描述整个过程的代码
DataSet dsResult = (查出来的表结果);
List<Dictionary<string, string>> dicList= ConvertToIEnumerable(dsResult);
List<object> list= GetEnumerable(dicList).ToDataSource();
//这样这个object就是个不用在项目中写cs文件定义的实体类
**********************
//想看具体属性的值就反射回来
foreach (object obj in list)
{
Dictionary<string, string> result = new Dictionary<string, string>();
System.Reflection.PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (System.Reflection.PropertyInfo item in properties)//获取该键值
{
string name = item.Name;
string value = item.GetValue(model, null).ToString();
result.Add(name, value);
}
}