在做项目的过程中发现有一种情况,就是实体类是不确定的,没办法写出对应的实体类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); } }