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()));
                        }
                    }
                }
  • 相关阅读:
    elastic search-php 多关键词查询实践(名称,日期,省份)
    记一次thinkphp 配置主从域名网站单点登录,退出
    thinkphp6 解决登录session跨域
    php富文本图片传递 通用css更改
    ELASTIC-PHP + IK分词器 + THINKPHP6 初次使用 (关键词查询)
    think-queue 加 redis实现批量导入excel
    百度api根据ip获取省市区
    php使用GD库将图片圆角 解决背景变黑问题 以及 图片丢失问题
    在树莓派上实现截图
    Arduino入门实践(五)--1、关于lcd的成像原理
  • 原文地址:https://www.cnblogs.com/xiaodlll/p/3822618.html
Copyright © 2011-2022 走看看