首页 > 其他 > 详细

通过XML动态创建模型

时间:2015-03-27 19:43:15      阅读:213      评论:0      收藏:0      [点我收藏+]
技术分享
  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 }
代码

 

通过XML动态创建模型

原文:http://www.cnblogs.com/xpfeng/p/4372351.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!