利用TypeBuilder是可以动态创建一个类型,现在有个需求,动态生成一个dll,创建类型EmployeeEx,需要继承原dll里面的Employee类,并包含Employee类上的所有类标记。
网上有很多例子,
//创建TypeBuilder。 TypeBuilder myTypeBuilder = myModBuilder.DefineType(typeName, TypeAttributes.Public); myTypeBuilder.SetParent(type);
大概处理方式如下:
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(typeof(SerializableAttribute).GetConstructor(Type.EmptyTypes), new Type[] { }); myTypeBuilder.SetCustomAttribute(customAttributeBuilder); att = type.GetCustomAttributes(typeof(DefaultPropertyAttribute), false); if (att != null && att.Length > 0) { DefaultPropertyAttribute dea = att[0] as DefaultPropertyAttribute; customAttributeBuilder = new CustomAttributeBuilder(typeof(DefaultPropertyAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { dea.Name }); myTypeBuilder.SetCustomAttribute(customAttributeBuilder); }
但是,这些都是已知类标记是Serializable或者DefaultProperty,如果原dll中的Employee再加个自定义标记,我们还需要再改程序,如何能够动态继承到类标记,TypeBuilder.SetCustomAttribute提供了2个重载SetCustomAttribute(CustomAttributeBuilder customBuilder)和SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)。这两个都是需要ConstructorInfo来构造类标记。而我们通过类型Employee得到的类标记是通过反射得到的object[] atts = type.GetCustomAttributes(false);这是object数组,不能直接给ConstructorInfo使用。
所以就有了下面的代码,来动态产生标记。
#region 标记 object[] atts = type.GetCustomAttributes(false); if (atts != null && atts.Length > 0) { foreach (Attribute item in atts) { if (item == null) continue; try { CustomAttributeBuilder c = null; ConstructorInfo[] conInfos = item.GetType().GetConstructors(); ConstructorInfo cons = conInfos[conInfos.Length - 1]; ParameterInfo[] args = cons.GetParameters(); List<Type> argsList = new List<Type>(); List<object> argsValue = new List<object>(); if (args.Length > 0) { foreach (var arg in args) { argsList.Add(arg.ParameterType); PropertyInfo pi = item.GetType().GetProperty(arg.Name.Substring(0, 1).ToUpper() + arg.Name.Substring(1));//微软规则首字母小写 if (pi != null) { argsValue.Add(pi.GetValue(item, null)); } else { pi = item.GetType().GetProperty(arg.Name.Remove(0, 1));//我们的规则p+Name if (pi != null) { argsValue.Add(pi.GetValue(item, null)); } else { argsValue.Add(null); } } } } PropertyInfo[] pis = item.GetType().GetProperties(); if (pis.Length > 0) { List<PropertyInfo> piList = new List<PropertyInfo>(); List<object> valueList = new List<object>(); object[] pValues = new object[pis.Length]; for (int i = 0; i < pis.Length; i++) { if (pis[i].CanWrite) { pValues[i] = pis[i].GetValue(item, null); if (pValues[i] != null) { piList.Add(pis[i]); valueList.Add(pValues[i]); } } } if (piList.Count > 0) { c = new CustomAttributeBuilder(cons, argsValue.ToArray(), piList.ToArray(), valueList.ToArray()); } else { c = new CustomAttributeBuilder(cons, argsValue.ToArray()); } } else { c = new CustomAttributeBuilder(cons, argsValue.ToArray()); } myTypeBuilder.SetCustomAttribute(c); } catch (Exception ex) { throw new Exception(string.Format("{0}的标记[{1}]重写异常:{2}", typeName, item.ToString(),ex.ToString())); } } }