1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Reflection.Emit; 6 using System.Text; 7 using System.Threading.Tasks; 8 using CommonClass; 9 using System.Xml; 10 using System.Data; 11 using System.Configuration; 12 13 namespace DynamicCreate 14 { 15 /// <summary> 16 /// 创建动态模型 17 /// </summary> 18 public class DynamicClass 19 { 20 /// <summary> 21 /// 模型集合 22 /// Key:模型名称 23 /// Value:类型 24 /// </summary> 25 public static Dictionary<string, Type> ModelType { get;private set; } 26 27 static DynamicClass() 28 { 29 DynamicClass.ModelType = new Dictionary<string, Type>(); 30 DynamicClass.Init();//初始化 31 } 32 /// <summary> 33 /// 初始化 34 /// </summary> 35 public static void Init() 36 { 37 string url = "ModelStruct.xml"; 38 var config=ConfigurationManager.ConnectionStrings["DynamicXmlUrl"]; 39 if (config != null)//如果有设置路径 则不使用默认路径 40 { 41 url = config.ConnectionString; 42 } 43 XmlDocument xml = new XmlDocument(); 44 xml.Load(url);//加载XML 45 XmlNode configNode = xml.SelectSingleNode("Config");//获得根节点 46 XmlNode nsNode = configNode.SelectSingleNode("NameSpace");//获得命名空间 47 XmlNode preNode = configNode.SelectSingleNode("TablePre");//获得表前缀 48 string nameSpace = ""; 49 string tablePre = ""; 50 if (nsNode == null)//如果没有改节点 51 { 52 nameSpace = "Mode"; 53 } 54 else 55 { 56 nameSpace = nsNode.InnerText; 57 if (string.IsNullOrEmpty(nameSpace))//判断值是否为空 58 { 59 nameSpace = "Model"; 60 } 61 } 62 if (preNode != null)//如果没有改节点 63 { 64 tablePre = preNode.InnerText; 65 } 66 XmlNodeList tableNodes = configNode.SelectNodes("Table");//获得表节点 67 AssemblyName DemoName = new AssemblyName(nameSpace);//动态创建程序集 68 AssemblyBuilder assBui = AssemblyBuilder.DefineDynamicAssembly(DemoName, AssemblyBuilderAccess.RunAndCollect); 69 //动态创建模块 70 ModuleBuilder mb = assBui.DefineDynamicModule(nameSpace);//创建模块 71 foreach (XmlNode tableNode in tableNodes) 72 { 73 //循环表节点 74 DynamicClass.DynamicCreateType(tableNode, mb, tablePre); 75 } 76 xml.Clone(); 77 } 78 79 /// <summary> 80 /// 生成类型 81 /// </summary> 82 /// <param name="name"></param> 83 /// <returns></returns> 84 private static void DynamicCreateType(XmlNode tableNode,ModuleBuilder mb,string tablePre) 85 { 86 string tableName = (tableNode as XmlElement).GetAttribute("Name");//获得表名 87 string className = string.Format("{0}Model", tableName);//类名 88 if (string.IsNullOrEmpty(tableName))//如果名称为空 89 { 90 throw new XmlModelException("错误:Table节点不能缺少Name"); 91 } 92 if (DynamicClass.ModelType.ContainsKey(className))//判断是否有该类 93 { 94 throw new XmlModelException(string.Format("{0}错误:已经存在 Table节点的Name不能重复", tableName)); 95 } 96 XmlNodeList columnNodes = tableNode.SelectNodes("Column");//获得列节点 97 //动态创建类 98 TypeBuilder tb = mb.DefineType(className, TypeAttributes.Public, typeof(CommonClass.ModelBase)); 99 tb.SetCustomAttribute(new CustomAttributeBuilder( 100 typeof(TableAttribute).GetConstructor(new Type[] { typeof(string) }), 101 new object[] {string.Format("{0}{1}",tablePre,tableName) })); 102 foreach (XmlNode columnNode in columnNodes) 103 { 104 //循环列节点 105 XmlElement xe = columnNode as XmlElement;//获得元素 106 string proName = xe.GetAttribute("Name");//获得属性名 107 string proTypeStr = xe.GetAttribute("Type");//获得属性类型 108 if (string.IsNullOrEmpty(proName))//判断属性名 109 { 110 throw new XmlModelException(string.Format("{0}错误:列节点缺少Name(属性名)", tableName)); 111 } 112 if (string.IsNullOrEmpty(proTypeStr))//判断列名 113 { 114 throw new XmlModelException(string.Format("{0}错误:列节点缺少Type(属性类型)", tableName)); 115 } 116 if (proTypeStr == "Int") 117 { 118 proTypeStr = "System.Int32"; 119 } 120 else if (!proTypeStr.Contains("System"))//如果没有包含System命名空间 121 { 122 proTypeStr = string.Format("System.{0}", proTypeStr); 123 } 124 Type proType = Type.GetType(proTypeStr); 125 List<CustomAttributeBuilder> cusAttrs = DynamicClass.GetAttrCus(columnNode,className);//获得构造集合 126 DynamicClass.AddPro(tb, proName, proType, cusAttrs); 127 } 128 129 130 131 //使用动态类创建类型 132 Type classType = tb.CreateType(); 133 134 //返回类型 135 DynamicClass.ModelType.Add(className, classType);//添加 136 } 137 138 /// <summary> 139 /// 添加属性 140 /// </summary> 141 /// <param name="type">类型</param> 142 /// <param name="proName">属性名</param> 143 /// <param name="proType">属性类型</param> 144 private static void AddPro(TypeBuilder type, string proName, Type proType,List<CustomAttributeBuilder> cusAttrs) 145 { 146 ///字段 147 FieldBuilder field = type.DefineField(string.Format("_{0}", proName), proType, FieldAttributes.Private); 148 PropertyBuilder pb = type.DefineProperty(proName, System.Reflection.PropertyAttributes.Reserved2, proType, null); 149 150 //get访问器 151 MethodBuilder getMethod = type.DefineMethod(string.Format("get_{0}", proName), MethodAttributes.Public, proType, Type.EmptyTypes); 152 //生成指令 153 ILGenerator getIL = getMethod.GetILGenerator(); 154 getIL.Emit(OpCodes.Ldarg_0); 155 getIL.Emit(OpCodes.Ldfld, field); 156 getIL.Emit(OpCodes.Ret); 157 pb.SetGetMethod(getMethod); 158 159 ////set访问器 160 MethodBuilder setMethod = type.DefineMethod(string.Format("set_{0}", proName), MethodAttributes.Public, null, new Type[] { proType }); 161 //生成指令 162 ILGenerator setIL = setMethod.GetILGenerator(); 163 setIL.Emit(OpCodes.Ldarg_0); 164 setIL.Emit(OpCodes.Ldarg_1); 165 setIL.Emit(OpCodes.Stfld, field); 166 setIL.Emit(OpCodes.Ret); 167 pb.SetSetMethod(setMethod); 168 169 //添加特性 170 foreach (CustomAttributeBuilder cusAttr in cusAttrs) 171 { 172 pb.SetCustomAttribute(cusAttr); 173 } 174 175 } 176 177 178 /// <summary> 179 /// 获得特性构造 180 /// </summary> 181 /// <param name="columnNode"></param> 182 /// <returns></returns> 183 private static List<CustomAttributeBuilder> GetAttrCus(XmlNode columnNode,string name) 184 { 185 List<CustomAttributeBuilder> cusAttrs = new List<CustomAttributeBuilder>();//特性构造集合 186 XmlElement xe = columnNode as XmlElement;//获得元素 187 string columnName = xe.GetAttribute("ColumnName"); 188 string dbTypeStr = xe.GetAttribute("DbType");//获得属性名 189 bool isPrimaryKey = columnNode.SelectSingleNode("IsPrimaryKey") != null;//判断是否主键 190 bool unique = columnNode.SelectSingleNode("Unique") != null;//判断是否唯一 191 bool notUpdate = columnNode.SelectSingleNode("NotUpdate") != null;//判断是否唯一 192 bool notInsert = columnNode.SelectSingleNode("NotInsert") != null;//判断是否唯一 193 bool notNull = columnNode.SelectSingleNode("NotNull") != null;//判断是否唯一 194 string chineseName = xe.GetAttribute("ChineseName");//获得中文名称 195 if (string.IsNullOrEmpty(columnName))//判断列名 196 { 197 throw new XmlModelException(string.Format("{0}错误:列节点缺少ColumnName(列名)", name)); 198 } 199 if (string.IsNullOrEmpty(dbTypeStr))//判断类型 200 { 201 throw new XmlModelException(string.Format("{0}错误:列节点缺少DbType(列类型)", name)); 202 } 203 if (isPrimaryKey && unique) 204 { 205 throw new XmlModelException(string.Format("{0}错误:Unique和IsPrimary不能同时存在", name)); 206 } 207 if (dbTypeStr == "Int") 208 { 209 dbTypeStr = "Int32"; 210 } 211 DbType dbType; 212 bool parseEnum = Enum.TryParse<DbType>(dbTypeStr,out dbType);//转换 213 if (!parseEnum)//判断结果 214 { 215 throw new XmlModelException(string.Format("{0}错误:DbType不正确", name)); 216 } 217 Type stringType = typeof(string), boolType = typeof(bool), enumType = typeof(DbType);//构造参数类型 218 ConstructorInfo columnCus = typeof(ColumnAttribute).GetConstructor(new Type[6]{ 219 stringType,enumType,boolType,boolType,boolType,stringType 220 });//获得列特性的构造函数 221 222 cusAttrs.Add(new CustomAttributeBuilder(typeof(FormAttribute).GetConstructor(new Type[] { }), new object[] { })); 223 //添加 224 cusAttrs.Add(new CustomAttributeBuilder(columnCus, new object[6] { columnName, dbType, notUpdate, notInsert, notNull, chineseName })); 225 if (isPrimaryKey) 226 { 227 //如果是主键 228 cusAttrs.Add(new CustomAttributeBuilder(typeof(PrimaryKeyAttribute).GetConstructor(new Type[] { }), new object[] { })); 229 } 230 if (unique) 231 { 232 //如果是唯一 233 cusAttrs.Add(new CustomAttributeBuilder(typeof(UniqueAttribute).GetConstructor(new Type[] { }), new object[] { })); 234 } 235 return cusAttrs; 236 } 237 238 /// <summary> 239 /// 获得对象 240 /// </summary> 241 /// <param name="name"></param> 242 /// <returns></returns> 243 public static ModelBase GetModelObject(string name) 244 { 245 if (!DynamicClass.ModelType.ContainsKey(name)) 246 { 247 throw new XmlModelException(string.Format("不存在模型:{0}", name)); 248 } 249 return Activator.CreateInstance(ModelType[name]) as ModelBase; 250 } 251 } 252 }
原文:http://www.cnblogs.com/xpfeng/p/4372351.html