欄位未知的Datatable轉成ObserObservableCollection<T>對象

发布于:2024-10-09 ⋅ 阅读:(110) ⋅ 点赞:(0)

這裡有兩個問題點:

1.如何將Datatable各欄位名稱和數據類型動態生成 一個類的實例.

2.如何將類的實例(變量,不是類型)作為T(泛型)傳入,並返回為T;

解決辦法:

第一步.判斷當前程序集,有無要生成的類,

A.如果有,則動態調用類的實例,

B.如果沒有,則生成代碼文件(供下次編譯時,直接編譯成類即可,提升代碼運行效率),再將代碼文件動態編譯成類,再調用;

第二步.在第一步得到的類是類的實例,不是類型,需要將實例透過轉化為類型T;

代碼如下:

#region 生成自定义动态类
public class Dyn_CreateClass
    {
        private DataTable ThisDt;
                    private string ForCreateClassName;
              string Mynamespace= System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;
        public Dyn_CreateClass(string CreateClassname, DataTable SourceDt)
        {
            if (CreateClassname.IndexOf("_") == -1)
            {
                MessageBox.Show("要創建的類名不符合要求");
            }
            this.ForCreateClassName = CreateClassname;
            ThisDt = SourceDt.Clone();
        }

        private class ColumnInfor
        {
            public string Name { get; set; }
            public Type datatype { get; set; }
        }
        private List<ColumnInfor> GetDatatableColsinfor()
        {
            List<ColumnInfor> lc = new List<ColumnInfor>();
            foreach (DataColumn item in ThisDt.Columns)
            {
                lc.Add(new ColumnInfor() { Name = item.ColumnName, datatype = item.DataType });
            }
            return lc;
        }
        public bool FindClassInthisApp()
        {
            Assembly assm3 = Assembly.GetExecutingAssembly();
            string assemblyname = assm3.GetName().Name;
            Type[] typesToRegister = assm3
                .GetTypes()
                .Where(type => !String.IsNullOrEmpty(type.Namespace))
                .Where(type => type.FullName.Contains(assemblyname))
                .Where(tppe => tppe.Name == ForCreateClassName)
                .ToArray<Type>();
            return typesToRegister.Length > 0;
        }
        private object CreateClass(Assembly assembly)
        {
            Type type = assembly.GetType(Mynamespace+"."+ForCreateClassName);

            // 创建该类的实例
            object obj = Activator.CreateInstance(type);
            // 返回新创建的类
            return obj;
        }
        private object Dyn_LoadClass()
        {
            Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
            Type o = Type.GetType(Mynamespace + "." + ForCreateClassName);//加载类型
            object obj = Activator.CreateInstance(o, true);//根据类型创建实例
            return obj;
        }
        public object  GenerateCode()
        {
            if (FindClassInthisApp())
                return Dyn_LoadClass();
            /*注意,先导入下面的命名空间
            using System.CodeDom
            using System.CodeDom.Compiler;
            using Microsoft.CSharp;
            using System.Reflection;
            */
            //准备一个代码编译器单元
            CodeCompileUnit unit = new CodeCompileUnit();
            //准备必要的命名空间(这个是指要生成的类的空间)
            CodeNamespace sampleNamespace = new CodeNamespace(Mynamespace);
            //导入必要的命名空间
         //   sampleNamespace.Imports.Add(new CodeNamespaceImport("System"));
            //准备要生成的类的定义
            CodeTypeDeclaration Customerclass = new CodeTypeDeclaration(ForCreateClassName);
            //指定这是一个Class
            Customerclass.IsClass = true;
            Customerclass.TypeAttributes = TypeAttributes.Public;
            //把这个类放在这个命名空间下
            sampleNamespace.Types.Add(Customerclass);
            //把该命名空间加入到编译器单元的命名空间集合中
            unit.Namespaces.Add(sampleNamespace);
            //这是输出文件
            string outputFile = "../../../AutoCreateClass/" + ForCreateClassName+".cs";
            添加字段
            List<ColumnInfor> datainfor = GetDatatableColsinfor();
            datainfor.ForEach(column =>
            {
                CodeMemberField field = new CodeMemberField(column.datatype, column.Name +" { get; set; }//");
                field.Attributes = MemberAttributes.Public;
                Customerclass.Members.Add(field);
            });
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BracingStyle = "C";
            options.BlankLinesBetweenMembers = true;
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile))
            {
                provider.GenerateCodeFromCompileUnit(unit, sw, options);
            }
           string treefile= File.ReadAllText(outputFile);
            Assembly newassamly=GenerateAssemblyFromCode(treefile); ;
            return CreateClass(newassamly);
        }
        public static Assembly GenerateAssemblyFromCode(string code)
        {
            Assembly assembly = null;
            // 丛代码中转换表达式树
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
            // 随机程序集名称
            string assemblyName = System.IO.Path.GetRandomFileName();
            // 引用
         //   var references = AppDomain.CurrentDomain.GetAssemblies().Select(x => MetadataReference.CreateFromFile(x.Location));
            MetadataReference[] references = new MetadataReference[]
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
    MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
};
            try
            {
                // 创建编译对象
                CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
                using (var ms = new MemoryStream())
                {
                    // 将编译好的IL代码放入内存流
                    EmitResult result = compilation.Emit(ms);
                    // 编译失败,提示
                    if (!result.Success)
                    {
                        IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                                    diagnostic.IsWarningAsError ||
                                    diagnostic.Severity == DiagnosticSeverity.Error);
                        foreach (Diagnostic diagnostic in failures)
                        {
                            Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                        }
                    }
                    else
                    {
                        // 编译成功,从内存中加载编译好的程序集
                        ms.Seek(0, SeekOrigin.Begin);
                        assembly = Assembly.Load(ms.ToArray());
                    }
                }
            }
            catch (Exception ex)
            {
            }
                return assembly;
        }
        /// <summary>
        /// 给属性赋值
        /// </summary>
        /// <param name="objclass">先进行dynamic objclass = assembly.CreateInstance(className),得到的objclass</param>
        /// <param name="propertyname">属性名称</param>
        /// <param name="value">属性值</param>
        public static void ReflectionSetValue(object objclass, string propertyname, object value)
        {
            PropertyInfo[] infos = objclass.GetType().GetProperties();
            try
            {
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyname && info.CanWrite)
                    {
                        info.SetValue(objclass, value, null);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 得到属性值
        /// </summary>
        /// <param name="objclass">先进行dynamic objclass = assembly.CreateInstance(className),得到的objclass</param>
        /// <param name="propertyname">属性名称</param>
        /// <returns>属性值,是object类型,使用时记得转换</returns>
        public static object ReflectionGetValue(object objclass, string propertyname)
        {
            object result = null;
            PropertyInfo[] infos = objclass.GetType().GetProperties();
            try
            {
                foreach (PropertyInfo info in infos)
                {
                    if (info.Name == propertyname && info.CanRead)
                    {
                        System.Console.WriteLine(info.GetValue(objclass, null));
                        result = info.GetValue(objclass, null);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                result = null;
            }
            return result;
        }
    }
    #endregion
    #region 類實例轉化為T,並將傳入的Datatable變為ObservableCollection<T>傳出
    public class TConverter
    {
        public object Deserializer<T>(DataTable dt) where T : class, new()
        {
            Type t = typeof(T);
            PropertyInfo[] propertys = t.GetProperties();
            ObservableCollection<T> lst = new ObservableCollection<T>();
            string typeName = string.Empty;
            foreach (DataRow dr in dt.Rows)
            {
                T entity = new();
                foreach (PropertyInfo pi in propertys)
                {
                    typeName = pi.Name;
                    if (dt.Columns.Contains(typeName))
                    {
                        if (!pi.CanWrite) continue;
                        object value = dr[typeName];
                        if (value == DBNull.Value) continue;
                        if (pi.PropertyType == typeof(string))
                        {
                            pi.SetValue(entity, value.ToString(), null);
                        }
                        else if (pi.PropertyType == typeof(int) || pi.PropertyType == typeof(int?))
                        {
                            pi.SetValue(entity, int.Parse(value.ToString()), null);
                        }
                        else if (pi.PropertyType == typeof(DateTime?) || pi.PropertyType == typeof(DateTime))
                        {
                            pi.SetValue(entity, DateTime.Parse(value.ToString()), null);
                        }
                        else if (pi.PropertyType == typeof(float))
                        {
                            pi.SetValue(entity, float.Parse(value.ToString()), null);
                        }
                        else if (pi.PropertyType == typeof(double))
                        {
                            pi.SetValue(entity, double.Parse(value.ToString()), null);
                        }
                        else
                        {
                            pi.SetValue(entity, value, null);
                        }
                    }
                }
                lst.Add(entity);
            }
            return lst;
        }
    }
    public static class Extend
    {
       public static object ToObservable匿名類(this DataTable dt,object obj )
        {
            Type type = obj.GetType();
            TConverter Td = new TConverter();
            MethodInfo Method = Td.GetType().GetMethod("Deserializer").MakeGenericMethod(new Type[] { type });
            object[] _args = new object[1] { dt };
            return Method.Invoke(Td, _args);
        }
}
    #endregion


网站公告

今日签到

点亮在社区的每一天
去签到