.net 反射构造你自己的“匿名”对象
由于近来项目的底层架构某些特殊需求及场景的需要要求动态build一个对象,
属性名称个类与类型都是外界动态传入的。
不多说废话,直接上我最原始的代码:
public static Type GetMyType()
{
string[] namelist = new string[] { "UserName", "UserID" };
Dictionary<string, Type> dic = new Dictionary<string, Type>();
dic.Add("UserName", typeof(string));
dic.Add("UserID", typeof(int)); string strDynamicModuleName = "jksdynamic";
string strDynamicClassName = "<>jksdynamci";
AppDomain currentDomain = System.AppDomain.CurrentDomain;
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = strDynamicModuleName; AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(strDynamicModuleName); TypeBuilder typeBuilder = moduleBuilder.DefineType(strDynamicClassName, TypeAttributes.Public); Type[] methodArgs = { typeof(string) }; ConstructorBuilder constructorBuiler = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(string), typeof(int) }); // typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard);
//typeBuilder.d
//动态创建字段
// FieldBuilder fb = typeBuilder.DefineField(item, typeof(System.String), FieldAttributes.Private);
//ILGenerator ilg = constructorBuiler.GetILGenerator();//生成 Microsoft 中间语言 (MSIL) 指令
//ilg.Emit(OpCodes.Ldarg_0);
//ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
//ilg.Emit(OpCodes.Ldarg_0);
//ilg.Emit(OpCodes.Ldarg_1); ////ilg.Emit(OpCodes.Stfld);
//ilg.Emit(OpCodes.Ret); int index = ;
ILGenerator ilg = constructorBuiler.GetILGenerator();
foreach (string item in dic.Keys)
{ //typeBuilder.DefineConstructor(MethodAttributes.Assembly, CallingConventions.VarArgs, new Type[] { typeof(string), typeof(int) }); //动态创建字段
//FieldBuilder fb = typeBuilder.DefineField("_" + item, dic[item], FieldAttributes.Private); //类型的属性成员由两部分组成,一是私有字段,二是访问私有字段的属性包装器。
//包装器运行时的本质与 Method 一样,即包含 Set_Method 和 Get_Method 两个方法。
//动态创建字段
FieldBuilder fieldBuilder = typeBuilder.DefineField(dic[item].Name + "_" + item, dic[item], FieldAttributes.Public); //FieldBuilder conFieldBuilder = typeBuilder.DefineField(item.ToLower(), dic[item], FieldAttributes.Public); index++;
ilg.Emit(OpCodes.Ldarg_0);//向MSIL流发送属性实例
ilg.Emit(OpCodes.Ldarg, index);//将指定索引的参数加到堆栈上。
ilg.Emit(OpCodes.Stfld, fieldBuilder);//装载字段 //ilg.Emit(OpCodes.Stfld, fieldBuilder); PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(item, PropertyAttributes.None, dic[item], null);
//MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
MethodBuilder methodBuilder = typeBuilder.DefineMethod("get_" + item, MethodAttributes.Public, dic[item], null); ILGenerator ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld, fieldBuilder);//装载属性私有字段
ilGenerator.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(methodBuilder);// 设置获取属性值的方法 methodBuilder = typeBuilder.DefineMethod("set_" + item,
MethodAttributes.Public,
typeof(void), new Type[] { dic[item] }); ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Stfld, fieldBuilder);
ilGenerator.Emit(OpCodes.Ret);
propertyBuilder.SetSetMethod(methodBuilder);// 设置属性值的方法 }
ilg.Emit(OpCodes.Ret);
Type type = typeBuilder.CreateType(); //Type typeDynamic = moduleBuilder.GetType(strDynamicClassName);
//object objReturn = Activator.CreateInstance(typeDynamic, "Admin", 90); object objReturn = Activator.CreateInstance(type, "Admin", ); return type; }
特别说:
ldarg.0微软官网上的说明,这里不做翻译比较简单。
NOTE: ldarg.0 holds the "this" reference - ldarg.1, ldarg.2, and ldarg.3
hold the actual passed parameters. ldarg.0 is used by instance methods
to hold a reference to the current calling object instance. Static methods
do not use arg.0, since they are not instantiated and hence no reference
is needed to distinguish them.
测试代码如下:
public static void TestCreateType()
{
Type myDynamicType = GetMyType();
Console.WriteLine("Some information about my new Type '{0}':",
myDynamicType.FullName);
Console.WriteLine("Assembly: '{0}'", myDynamicType.Assembly);
Console.WriteLine("Attributes: '{0}'", myDynamicType.Attributes);
Console.WriteLine("Module: '{0}'", myDynamicType.Module);
Console.WriteLine("Members: ");
foreach (MemberInfo member in myDynamicType.GetMembers())
{
Console.WriteLine("-- {0} {1};", member.MemberType, member.Name);
}
Console.WriteLine("---");
Type[] aPtypes = new Type[] { typeof(string), typeof(int) }; object[] aPargs = new object[] { "JksName", }; ConstructorInfo myDTctor = myDynamicType.GetConstructor(aPtypes);
Console.WriteLine("Constructor: {0};", myDTctor.ToString()); Console.WriteLine("---"); object amyclass = myDTctor.Invoke(aPargs);
Console.WriteLine("aPoint is type {0}.", amyclass.GetType()); //Console.WriteLine("aPoint.x = {0}",
// myDynamicType.InvokeMember("get_UserName",
// BindingFlags.InvokeMethod,
// null,
// myDTctor,
// new object[0]));
Console.WriteLine("Method ---");
foreach (MethodInfo method in myDynamicType.GetMethods())
{
if (method.Name.StartsWith("get_"))
{
object v = method.Invoke(amyclass, null);
Console.WriteLine(method.Name + " : " + v.ToString());
}
}
Console.WriteLine("Property ---");
foreach (PropertyInfo property in myDynamicType.GetProperties())
{ Console.WriteLine(property.Name + " : " + property.GetValue(amyclass).ToString()); } }
运行结果如下:

.net 反射构造你自己的“匿名”对象的更多相关文章
- 匿名对象 构造方法 重载 构造代码块 this 关键字
一.匿名对象 1.匿名对象 :没有名字对象 2.匿名对象的使用注意点: 1.我们一般不会用匿名对象给属性赋值,无法获取属性值. 2.匿名对象永远都不可能事一个对象. 3.匿名对象的好处 : 书写简单. ...
- 构造 & 析构 & 匿名对象
以前仅知道创建对象,但对匿名对象的了解基本为0. 通过阅读google chromium源代码 中关于 log 的使用,查阅相关资料,了解了一下匿名对象,予以记录. 什么是匿名对象 匿名对象可以理 ...
- JAVA之旅(四)——面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块
JAVA之旅(四)--面向对象思想,成员/局部变量,匿名对象,封装 , private,构造方法,构造代码块 加油吧,节奏得快点了 1.概述 上篇幅也是讲了这点,这篇幅就着重的讲一下思想和案例 就拿买 ...
- Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员、局部),匿名对象的调用,构造代码块(5)
Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员.局部),匿名对象的帝爱用,构造代码块(5)
- 当类型为dynamic的视图模型遭遇匿名对象
当年在ASP.NET MVC 1.0时代我提到,在开发时最好将视图的Model定制为强类型的,这样可以充分利用静态检查功能进行排错.不过有人指出,这么做虽然易于静态检查,但是定义强类型的Model类型 ...
- C++不能显式调用构造函数,会生成匿名对象,这点与Java完全不一样!
Java可以直接调用同名构造函数,仅仅起初始化的功能,并不构造新的对象,但是C++里面没有.看一下这段代码: class A { public: A() { printf("A() \n&q ...
- c# 匿名对象增加动态属性
在开发过程中碰到了一个需求,需要动态创建对象及其动态属性.在尝试几种方法后,最后完成了需求,记录下过程,给园友参考下 1.动态创建对象一:匿名对象 ",Birthday =DateTime. ...
- C# 匿名对象(匿名类型)、var、动态类型 dynamic
本文是要写的下篇<C#反射及优化用法>的前奏,不能算是下一篇文章的基础的基础吧,有兴趣的朋友可以关注一下. 随着C#的发展,该语音内容不断丰富,开发变得更加方便快捷,C# 的锋利尽显无疑. ...
- LINQ学习系列-----1.4 匿名对象
本篇内容接着上一篇继续讲述,本篇简单讲解匿名对象 一.匿名对象介绍 上代码: var result=new { ID=, Name="张三", Age= ...
随机推荐
- 用Q-learning算法实现自动走迷宫机器人
项目描述: 在该项目中,你将使用强化学习算法,实现一个自动走迷宫机器人. 如上图所示,智能机器人显示在右上角.在我们的迷宫中,有陷阱(红色炸弹)及终点(蓝色的目标点)两种情景.机器人要尽量避开陷阱.尽 ...
- React Native组件解析(二)之Text
React Native组件解析(二)之Text 1. 概述 Text组件对应于iOS的UILabel,Android的TextView,用来显示文本.但是Text组件的内部使用的并不是flexbox ...
- 生成ssh密钥
打开Git Bash,生成ssh密钥: ssh-keygen -t rsa -C "your_email@youremail.com"
- 1492: [NOI2007]货币兑换Cash【CDQ分治】
1492: [NOI2007]货币兑换Cash Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 4166 Solved: 1736[Submit][Sta ...
- 使用注解来构造IoC容器-转
新手,对于一些觉得有用的东西,直接转过来用了,自己理解的比较肤浅 使用注解来构造IoC容器 用注解来向Spring容器注册Bean.需要在applicationContext.xml中注册<co ...
- Java,获取文件的Base64字符串,解码Base64字符串还原文件
在jdk1.8以前,获取文件Base64字符串需要用到第三方库,从1.8开始,Java中引入了Base64相关的类 以下是代码示例 获取文件的Base64编码字符串 import java.io.Fi ...
- eclipse配置SVN
1.设置 maven 工程svn忽略target 最新maven写法忽略的文件,还需忽略target.*/logs. Windows -> Preferences -> Team -> ...
- 一个selenium笔试题——去哪网首页获取符合要求的url并保存
今天在群里看到这样一个笔试题:请使用任何熟悉的面向对象编程语言,编写代码,获取http://www.qyer.com页面中,所有</a>标签"href"属性值包含英文单 ...
- FLV文件格式解析(转)
FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧.封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式.另外由于当前浏览器与F ...
- 动态注册BroadcastReceiver
1. [代码][Java]代码 package com.zjt.innerreceiver; import android.app.Service; import android.con ...