关于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()));
}
}
}
关于Emit中动态类型TypeBuilder创建类标记的一点思考的更多相关文章
- c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic
比如有一个匿名对象,var result =......Select( a=>new { id=a.id, name=a.name});然后Object obj = result ;我怎 ...
- 自己动手之使用反射和泛型,动态读取XML创建类实例并赋值
前言: 最近小匹夫参与的游戏项目到了需要读取数据的阶段了,那么觉得自己业余时间也该实践下数据相关的内容.那么从哪入手呢?因为用的是Unity3d的游戏引擎,思来想去就选择了C#读取XML文件这个小功能 ...
- mvc中动态给一个Model类的属性设置验证
原文:mvc中动态给一个Model类的属性设置验证 在mvc中有自带的验证机制,比如如果某个字段的类型是数字或者日期,那么用户在输入汉字或者英文字符时,那么编译器会自动验证并提示用户格式不正确,不过这 ...
- Swift微博项目--Swift中通过类名字符串创建类以及动态加载控制器的实现
Swift中用类名字符串创建类(用到了命名空间) OC中可以直接通过类名的字符串转换成对应的类来操作,但是Swift中必须用到命名空间,也就是说Swift中通过字符串获取类的方式为NSClassFro ...
- Object-C中动态类型对象相关操作汇总
Object-C(以后简称OC)中有id类型,相对于明确定义类型的静态类型,称为动态类型. 使用动态类型,配合多态(不同类型拥有同名方法),动态绑定(运行时决定实际调用的方法)可以将很多判断延迟到运行 ...
- c# dynamic动态类型和匿名类
dynamic类型 简单示例 dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写 expando.Id = 1; e ...
- Unity 3D 中动态字体的创建
原创不易,转载请注明转自: http://blog.csdn.net/u012413679/article/details/26232453 ---- kosion 1.载入NGUI插件包,载入完毕后 ...
- Java中Date类型的工具类
package com.mytripod.util; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...
- Python中type()详解:动态创建类
众所周知: type()函数可以查看变量的类型: 先看一个简单的列子来看一下type查看变量类型 class Animal(): pass a=Animal() print(type(a)) prin ...
随机推荐
- Proguard 保留native methods的问题
发现一个奇怪的问题,如果使用下面的配置来keep的话,native的方法还是被删掉了,百思不得其解. -keepclasseswithmembers class * { native *; } ...
- SQL 增加或删除一列
SQL 增加或删除一列 alter table tablename drop column columnname;alter table tabelname add columnname varcha ...
- SATA接口硬盘加密器
加密卡置于主板与硬盘.光驱之间,透明实时地对写入数据进行加密,对读出数据进行解密,有效防止信息被窃.未经授权的阅读和修改,以及硬盘.光盘丢失.被盗.废弃.非法用户访问而引发的敏感信息泄密问题,为用户打 ...
- (转) Python in NetBeans IDE 8.0
原地址: https://blogs.oracle.com/geertjan/entry/python_in_netbeans_ide_8 Copy this to the clipboard: ht ...
- sql 更新一列为行号
update u_menu set issort=t1.rowId from ( --select * from --( select cmenu_id,ROW_NUMBER() over(O ...
- JavaScript 作用域和闭包
作用域的嵌套将形成作用域链,函数的嵌套将形成闭包.闭包与作用域链是 JavaScript 区别于其它语言的重要特性之一. 作用域 JavaScript 中有两种作用域:函数作用域和全局作用域. 在一个 ...
- [0] Tornado Todo 开篇
参考自: python: tornado例子 Github地址:tornado_todo 开发环境: Python包的安装: 首先安装 pip: sudo apt-get install python ...
- T4 模板自动生成带注释的实体类文件
T4 模板自动生成带注释的实体类文件 - 只需要一个 SqlSugar.dll 生成实体就是这么简单,只要建一个T4文件和 文件夹里面放一个DLL. 使用T4模板教程 步骤1 创建T4模板 如果你没有 ...
- BIN和HEX文件的区别
HEX文件和BIN文件是我们经常碰到的2种文件格式.下面简单介绍一下这2种文件格式的区别: 1.HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身.在烧写或下载HEX文件的时候,一般都不需要 ...
- 一个简单的webserver
用c语言写了一个web server,特别简单共计一个文件且不到200行. 当然目前的问题还有很多, 不支持php,对图片支持不好,日志功能还没有完善 这些后期都会加上! gcc server.c - ...