動態生成類在對于O/R Mapping來說有很大的作用,在實際應用中用到的一些場景,比如支持用戶自定義字段,自定義公式的解析、動態插件等等。
下面就詳細介紹一下Emit的實際應用:
Emit動態創建類型
目標:創建類型Employee,兩個簡單屬性:Name(姓名),BirthDate(生日) ,一個方法void PRopertyChanged(string propertyName)
其中Name必填,預設值“新同事”,String類型;BirthDate是日期類型
準備工作:定義類型EntityDictionary和DynamicField,用于動態產生實體類型。
public class EntityDictionary { private string _name; /// <summary> /// 實體名稱 /// </summary> public string Name { get { return _name; } set { _name = value; } } private string _caption; /// <summary> /// 顯示值 /// </summary> public string Caption { get { return _caption; } set { _caption = value; } } private List<string> _interfaceList; /// <summary> /// 接口列表 /// </summary> public List<string> InterfaceList { get { return _interfaceList; } set { _interfaceList = value; } } private List<DynamicField> _dynamicFieldList; /// <summary> /// 字段列表 /// </summary> public List<DynamicField> DynamicFieldList { get { return _dynamicFieldList; } set { _dynamicFieldList = value; } } }
public class DynamicField { private string _name; /// <summary> /// 字段名稱 /// </summary> public string Name { get { return _name; } set { _name = value; } } private string _entityName; /// <summary> /// 實體名稱 /// </summary> public string EntityName { get { return _entityName; } set { _entityName = value; } } private string _type; /// <summary> /// 類型 /// </summary> public string Type { get { return _type; } set { _type = value; } } private int _size; /// <summary> /// 長度 /// </summary> public int Size { get { return _size; } set { _size = value; } } private byte _scale; /// <summary> /// 小數位數 /// </summary> public byte Scale { get { return _scale; } set { _scale = value; } } private string _refType; /// <summary> /// 引用類型 /// </summary> public string RefType { get { return _refType; } set { _refType = value; } } private string _control; /// <summary> /// 顯示控件類型 /// </summary> public string Control { get { return _control; } set { _control = value; } } private string _caption; /// <summary> /// 顯示值 /// </summary> public string Caption { get { return _caption; } set { _caption = value; } } private bool _isRequired; /// <summary> /// 是否必填 /// </summary> public bool IsRequired { get { return _isRequired; } set { _isRequired = value; } } private string _defaultValue; /// <summary> /// 默認值 /// </summary> public string DefaultValue { get { return _defaultValue; } set { _defaultValue = value; } } private string _externInfo; /// <summary> /// 擴展信息 /// </summary> public string ExternInfo { get { return _externInfo; } set { _externInfo = value; } } private object _tempProperty; /// <summary> /// 保留欄位 /// </summary> public object TempProperty { get { return _tempProperty; } set { _tempProperty = value; } } }
1.創建類
首先我們看下產生dll的代碼:
public void Create() { AppDomain myDomain = Thread.GetDomain(); AssemblyName myAsmName = new AssemblyName(); myAsmName.Name = "TestDynamicAssembly"; myAsmName.Version = new Version("1.0.0.0"); //創建一個永久程序集,設置為AssemblyBuilderaccess.RunAndSave。 AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave); //設置版本號信息 myAsmBuilder.DefineVersionInfoResource("Test", myAsmName.Version.ToString(), "TestCorp", "Copyright ? TestCorp Limited 2014", ""); //創建一個永久單模程序塊。 ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(myAsmName.Name, myAsmName.Name + ".dll"); //通常采用xml讀取方式給DynamicField的屬性賦值,這里Demo采用簡單的直接賦值方式 List<DynamicField> listDynamicField = new List<DynamicField>(); DynamicField df = new DynamicField(); df = new DynamicField(); df.Name = "Name"; df.Caption = "姓名"; df.Type = "System.String"; df.IsRequired = true;//是否必填 df.DefaultValue = "新同事";//預設值 df.Size = 200;//字段長度 listDynamicField.Add(df); df.Name = "BirthDate"; df.Caption = "生日"; df.Type = "System.DateTime"; listDynamicField.Add(df); //通常采用Xml讀取方式給EntityDictionary的屬性賦值,這里Demo采用簡單的直接賦值方式 EntityDictionary ed = new EntityDictionary(); ed.Name = "Employee"; ed.Caption = "雇員信息"; ed.DynamicFieldList = listDynamicField;
//創建類型 CreateEntity(myModBuilder, ed);
//創建方法 AddMethordToTypeBuilder(myModBuilder); //保存程序集。 myAsmBuilder.Save(myAsmName.Name + ".dll"); }
主要代碼CreateEntity(創建類型)如下:
private void CreateEntity(ModuleBuilder myModBuilder, EntityDictionary ed) { //重寫命名空間 string typeName = string.Format("{0}.{1}", "TestDemo.DataEntity", ed.Name); //創建TypeBuilder。 TypeBuilder myTypeBuilder = myModBuilder.DefineType(typeName, TypeAttributes.Public); #region 類標記 //序列化 CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { }); myTypeBuilder.SetCustomAttribute(customAttributeBuilder); //這是個相對復雜的類型標記 定義了類型的主鍵和別名,有興趣可以研究一下 //if (!string.IsNullOrEmpty(df.Alias)) { // customAttributeBuilder = new CustomAttributeBuilder(typeof(DataEntityAttribute).GetConstructor(Type.EmptyTypes), new Type[] { }, new PropertyInfo[] { typeof(DataEntityAttribute).GetProperty("PrimaryKey"), typeof(DataEntityAttribute).GetProperty("Alias") }, new object[] { df.PrimaryKey, df.Alias }); //} else { // customAttributeBuilder = new CustomAttributeBuilder(typeof(DataEntityAttribute).GetConstructor(Type.EmptyTypes), new Type[] { }, new PropertyInfo[] { typeof(DataEntityAttribute).GetProperty("PrimaryKey") }, new object[] { df.PrimaryKey }); //} //myTypeBuilder.SetCustomAttribute(customAttributeBuilder); #endregion #region 接口 //對類型添加接口 //if (df.InterfaceList != null &&
新聞熱點
疑難解答