zoukankan      html  css  js  c++  java
  • 关于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 = 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()));
                        }
                    }
                }
  • 相关阅读:
    redis 秒杀设计,常用命令
    wamp下配置多域名和访问路径的方法
    git commit 因执行yarn , npm,报错推送不了
    taro bug--小程序报错Error: 未找到入口 sitemap.json 文件,或者文件读取失败,请检查后重新编译。
    vscode引用相对路径,scss时路径报错问题解决
    space-between与space-around的区别
    Android可设置任意高度的TextView,如:设置0.5px设置0.1px等等
    Android可以打开微信支付,但是没法调起小程序支付
    dask
    Joblib-lightweight piplining tool
  • 原文地址:https://www.cnblogs.com/xiaodlll/p/3822618.html
Copyright © 2011-2022 走看看