作者:JustRun

林肯: http://www.cnblogs.com/JustRun1983/p/3830764.html

代替Reflection(反射)的一些方法(转)

2014-07-08 08:00 by JustRun, 3942 阅读, 26 评论, 收藏, 编辑

Reflection(反射)是深入学习.Net必须掌握的技能之一。最初学Reflection的时候,的确是被惊住了,原来还可以这样。只要给你一个Assembly, 你就能获取到其中所有的类型,根据类型,你能够创建和操作对象的属性和方法,甚至是私有的。但是,每次使用Reflection,看着那些丑陋难懂的代码,都让人不敢直视。下面就介绍一些在特定场景下可以替换Reflection的方法。

1. 使用Reflection完成的简单Demo

我们首先创建一个Person类,这个类非常简单,一个Name的public属性,一个_age的私有变量。完整代码如下:

public
class Person

{

private
readonly
int _age;

public Person(int age)

{

_age = age;

}

public
string Name { get; set; }

public
bool GuessAge(int age)

{

return _age == age;

}

}

接下来,看看常规的使用reflection获取一个person对象公开属性,私有变量同时调用对象的方法:

var type = p.GetType();

var property = type.GetProperty("Name");//根据名称获取类型属性

Console.WriteLine(property.GetValue(p).ToString());//获取对象的属性值

var field = type.GetField("_age", BindingFlags.NonPublic | BindingFlags.Instance);//获取私有变量_age, 后面的BindingFlags非常重要,否则默认是不能够取到private的东西

Console.WriteLine(field.GetValue(p));

var guessResult = type.InvokeMember("GuessAge", BindingFlags.InvokeMethod, null, p, new
object[] { 20 });//调用对象的方法

Console.WriteLine(guessResult);

来看看输出结果:

2. 使用PrivateObject

什么是PrivateObject, PrivateObject是微软在单元测试中引入的,本意是方便我们写单元测试的时候,对于私有变量,方法,能够非常简单方便的调用。但是这也不妨碍我们在开发代码中使用。使用PrivateObject只需要引用Microft.VisualStudio.QualityTools.UnitTestFramework

接下来看看,如何使用PrivateObject来实现:

var privateObject = new PrivateObject(p);

Console.WriteLine(privateObject.GetProperty("Name"));

Console.WriteLine(privateObject.GetField("_age"));

 

Console.WriteLine(privateObject.Invoke("GuessAge", new
object[] { 20 }));

上面的代码和使用Reflection的效果完全一样。是不是觉得整个世界都清净许多。在代码的可读性上面,比Reflection好不少。

3. 使用dynamic

使用动态类型,可以非常简单方便的访问对象的属性的方法,比如上面的代码,如果我用dynamic实现:

dynamic person = p;

Console.WriteLine(person.Name);

//Console.WriteLine(person._age);

Console.WriteLine(person.GuessAge(20));

使用dynamic的前提是,你在写代码的时候,就需要知道该对象的确切的属性名字和方法名,不能作为参数传递。而上面的Refelction和PrivateObject是可以的。
使用dynamic还有一个缺点,就是无法访问到对象的私有成员。这也是注释掉_age输出的原因。

真实的使用场景是,可以在不需要定义接口的情况下,实现通用的代码。比如Person有个Start属性, Car也有个Start属性,有个功能是需要为由Start的东西,显示的时候,都要带个星星的图标,这个时候,使用dynamic,就能够写出同时支持Person和Car的方法。

4. 使用Exposed

使用dynamic不能访问私有成员的问题,在Exposed里得到完全解决,从名字(翻译成暴露)也能看出来,它就是干这个的。

var exposedObj = Exposed.From(p);

Console.WriteLine(exposedObj.Name);

Console.WriteLine(exposedObj._age);

Console.WriteLine(exposedObj.GuessAge(20));

Exposed是第三方开源的,项目地址是https://github.com/Cognifide/ExposedObject,也可以在nuget中下载到。

5. 大杀器Clay

看到上面的"废话",动态语言的爱好者只会冷笑一下,丑陋的静态编译语言,这些东西在动态语言里面,"这都不是事"。好吧,我承认,但是看完了Clay,也许能改变你的看法。

dynamic New = new ClayFactory();

var person = New.Person().Name("Louis")._age(30);

person.GuessAge = new Func<int, bool>(x => x == person._age);

Console.WriteLine(person.Name);

Console.WriteLine(person._age);

Console.WriteLine(person.GuessAge()(20));

跟多的了解Clay,可以看这篇http://www.cnblogs.com/JustRun1983/p/3529157.html

代替Reflection(反射)的一些方法(转)的更多相关文章

  1. 代替Reflection(反射)的一些方法

    Reflection(反射)是深入学习.Net必须掌握的技能之一.最初学Reflection的时候,的确是被惊住了,原来还可以这样.只要给你一个Assembly, 你就能获取到其中所有的类型,根据类型 ...

  2. Java进阶之reflection(反射机制)——反射概念与基础

    反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...

  3. 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

    反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法)   创建Delegate (1).Delegate.CreateDelegate(Type, ...

  4. Java Reflection 反射基础

    反射基础: package reflection; /** * Created by : Infaraway * DATE : 2017/3/2 * Time : 23:06 * Funtion : ...

  5. Groovy 反射字符串常量方法

    Keywords: Groovy, Reflection, 反射 The Reflection of Groovy String constant style method. Groovy支持以下的方 ...

  6. java学习--Reflection反射机制

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...

  7. C#中分别对委托、匿名方法、Lambda表达式、Lambda表达式树以及反射执行同一方法的过程进行比较。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. C#中的反射和扩展方法的运用

    前段时间做了一个练手的小项目,采用的是三层架构,也就是Models,IDAL,DAL,BLL 和 Web , 在DAL层中各个类中有一个方法比较常用,那就是 RowToClass ,顾名思义,也就是将 ...

  9. C# 反射Reflection——反射反射程序员的快乐

    一.什么是反射 反射Reflection:System.Reflection,是.Net Framework提供的一个帮助类库,可以读取并使用metadata. 反射是无处不在的,MVC-Asp.Ne ...

随机推荐

  1. vue.js 源代码学习笔记 ----- codegen.js

    /* @flow */ import { genHandlers } from './events' import { baseWarn, pluckModuleFunction } from '.. ...

  2. C#读写三菱Fx PLC 使用Fx 串口协议 读写Fx3U设备

    本文将使用一个Github开源的组件库技术来读写三菱 FX PLC,使用的是基于串口的实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 github地 ...

  3. 手动整合实现SSH项目开发02

    在bean包下建立User类和User.hbm.xml文件,实现User类和数据库表User的映射关系,具体User类不多说,User.hbm.xml如下: <?xml version=&quo ...

  4. [QT][DEMO] QTableWidget 设置某一列禁止编辑

    例程 : 又是好风景 : http://blog.csdn.net/qiao_yihan/article/details/46413345 关键点: 1.QTableWidgetItem 的 setF ...

  5. 每天一个linux命令(性能、优化):【转载】lsof命令

    lsof(list open files)是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件.所以如传输控制协议 ...

  6. MacBook下java环境的搭建

    在Mac下搭建JAVA环境: 1.下载并安装JDK: 下载最新的JDK,傻瓜式安装,一直下一步就OK了. 2.配置环境变量: 在终端中输入 sudo vim ~/.bash_profile ,打开 . ...

  7. 【java基础】ThreadLocal的实现原理

    [一]:ThreadLocal对象的大体实现原理===>当前线程对象有一个ThreadLocal.ThreadLocalMap属性.===>声明的ThreadLocal对象最终存储在当前线 ...

  8. C语言使用pthread多线程编程(windows系统)二

    我们进行多线程编程,可以有多种选择,可以使用WindowsAPI,如果你在使用GTK,也可以使用GTK实现了的线程库,如果你想让你的程序有更多的移植性你最好是选择POSIX中的Pthread函数库,我 ...

  9. redis的maxmemory与maxmemory-policy关系

    如果redis配置了maxmemory和maxmemory-policy策略,则当redis内存数据达到maxmemory时,会根据maxmemory-policy配置来淘汰内存数据,以避免OOM.r ...

  10. RabbitMQ消息队列安装

    [root@VM_119_179_centos ~]# rpm -ivh erlang-19.0.4-1.el6.x86_64.rpm [root@VM_119_179_centos ~]# rpm ...