首页 > 代码库 > 关于Emit中动态类型TypeBuilder创建类标记的一点思考

关于Emit中动态类型TypeBuilder创建类标记的一点思考

 

利用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 = http://www.mamicode.com/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()));                    }                }            }