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

简介:

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);
复制代码

来看看输出结果:

image

2. 使用PrivateObject

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

image

接下来看看,如何使用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



本文转自JustRun博客园博客,原文链接:http://www.cnblogs.com/JustRun1983/p/3830764.html,如需转载请自行联系原作者


目录
相关文章
|
4月前
|
缓存 安全 Java
反射带来的问题
反射带来的问题
36 0
|
7月前
|
API C# 数据库
C#反射详解
C#反射详解
64 0
|
XML 安全 Java
【javaSE】 反射与反射的使用
【javaSE】 反射与反射的使用
反射和反射的方法
反射和反射的方法
|
Java
Java Reflection机制 实现类的反射与动态调用
Java Reflection机制被广泛用于实现类的反射和动态调用,反射是指在运行时检查和操作类的能力。只需要一个类的名称或对象的引用,就可以获取类的信息,调用类的方法,创建对象实例等。
61 0
|
7月前
|
存储 Java API
Java中的Reflection(反射)、暴力反射
Java中的Reflection(反射)、暴力反射
|
存储 Java API
C#反射(Reflection)详解
反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。反射指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗一点:我们在获取其他实体类的字段名或实列,只能获取公有的,而有了反射之后可以获取私有的,可以获取他的基类等等,可以说把家底查得清清楚楚。
248 1
|
Java 关系型数据库 MySQL
C#反射(Reflection)详解及于java反射的对比
C#反射(Reflection)详解及于java反射的对比
|
设计模式 安全 Java
反射(reflection)详细讲解
反射(reflection)详细讲解
118 0
|
缓存 前端开发 JavaScript
一起来学反射(上)
一起来学反射
102 0