LINQ TO Reflection(反射)

简介:

引言

我们平时开发中不可避免,或者说,经常性的使用反射。但是却没有一个合适的类库帮助我们更好的利用反射。从早期的FastInvoker,到老赵的 fastreflectionlib ,无一不是在强调Fast。这是因为反射的性能损耗比较厉害,所以大家都集中精力解决性能的问题,但是在易用性方面却鲜有改进。今天我为大家带来一个即兼顾性能又具有良好的使用体验的反射类库.

.Metadata()

此类库以LINQ TO Object为基础,可以通过调用.Metadata()方法获取对应Type的完整Metadata信息。此信息会被进行缓存,并且使用fastreflectionlib的核心Lambda代码,利用DynamicMethod代替直接的反射执行。

        public static Metadata Metadata(this object instance)
{
return MetadataCache.Create(instance);
}

     先定义一个MockObject

        class MockAttribute : Attribute
{
public MockAttribute(string name)
{
this.Name = name;
}
public string Name
{
get;set;
}
}

class MockObject
{
public string Country = "China";

[Mock("this is the name")]
public string Name
{
get;set;
}
public string Blog
{
get;set;
}
[Mock("this is the location")]
public string Location
{
get;set;
}
public string SayHello(string name)
{
return "Hi," + name;
}
}
}

 

   1.如何获取一个属性,并进行取值、赋值?

        using Sparrow.Reflection;
[TestMethod]
public void set_property_value()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "XiaMen" };
var property = obj.Metadata().Properties.Where(i => i.Name == "Location").FirstOrDefault();
var changedLocation = "Xiamen,China";
//get value //var value = property.GetValue(obj); property.SetValue(obj, changedLocation); Assert.AreEqual(changedLocation, obj.Location); }

   2.如果获取一个字段的值?

        using Sparrow.Reflection;
[TestMethod]
public void get_field_value()
{
var obj = new MockObject();

var field = obj.Metadata().Fields.Where(i => i.Name == "Country").FirstOrDefault();

Assert.AreEqual("China", field.GetValue(obj));
}

   3.如何获取一个自定义CustomAttribute?

        using Sparrow.Reflection;
[TestMethod]
public void get_custom_attribute_data()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "XiaMen" };


var attribute = obj.Metadata().Properties
.Where(i => i.Name == "Name")
.SelectMany(i => i.Attributes)
.Select(i=>i.Attribute)
.OfType<MockAttribute>()
.FirstOrDefault();

Assert.AreEqual("this is the name", attribute.Name);
}

   4.如何调用一个指定名称的Method?

        using Sparrow.Reflection;
[TestMethod]
public void invoke_method()
{
var obj = new MockObject();

var method = obj.Metadata().Methods.Where(i => i.Name == "SayHello").FirstOrDefault();

Assert.AreEqual("Hi,world",method.Invoke(obj,new []{"world"}));
}

.Proxy()

对于某些应用场景来说,使用LINQ To Object去查询并获取单一的方法、属性,字段,总觉得还是要写非常多的代码。要先.Metadata(), 接下来.Where(), 虽然代码很优雅,但是还是有很多工作要做。所以这里也提供一个针对获取单一方法、属性、字段的替代写法。

        public static Proxy Proxy(this object instance)
{
return new Proxy(instance);
}

1.如何获取一个属性的值

        using Sparrow.Reflection;
[TestMethod]
public void get_value_via_property_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

Assert.AreEqual(obj.Name, obj.Proxy().Properties["Name"]);
}

 

2.如何设置一个属性的值

        using Sparrow.Reflection;
[TestMethod]
public void set_value_via_property_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

var changedLocation = "Xiamen,China";
obj.Proxy().Properties["Location"] = changedLocation;

Assert.AreEqual(changedLocation,obj.Location);
}
 
 

3.如何获取一个字段的值

        using Sparrow.Reflection;
[TestMethod]
public void get_value_via_field_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

Assert.AreEqual(obj.Country, obj.Proxy().Fields["Country"]);
}

 

4.如何调用一个方法

        using Sparrow.Reflection;
[TestMethod]
public void invoke_method_via_method_proxy()
{
var obj = new MockObject();

Assert.AreEqual("Hi,world", obj.Proxy().Methods["SayHello"](new []{"world"}));
}

.Proxy() Vs Dynamic

我们知道在C# 4中引入了关键字Dynamic,使得 Duck Typing (DynamicDuck: Duck Typing in a Dynamic World) 成为一种可能。 查看如下代码

        public void Run(dynamic obj)
{
Console.WriteLine(obj.Name);
}

 

这个代码并没有指定参数obj的类型,obj的类型是由运行时候传入的真实值决定,只要该类型包含一个Name的属性就可以了。

但是仅仅支持Duck Typing就够了嘛? 似乎不够动态哦。这边的.Name 是在编译时(或者说编码时)就确定,但是往往我们的使用场景中,连这个也都是动态,比如是接受自Form,或者来自配置信息,这个时候dynamic就无能为力了。

反过来看看使用.Proxy()的情况

       public void Run(object obj,string propertyName)
{
Console.WriteLine(obj.Proxy().Properties[propertyName])
}

 

 

不仅支持Duck Typing,同时也支持属性名称的动态化,是不是很有脚本(javascript…)的感觉呢?

代码下载http://sparrow.codeplex.com/releases/view/50364

详细文档http://sparrow.codeplex.com/wikipage?title=LINQ-To-Reflection

 


本文转自浪子博客园博客,原文链接:http://www.cnblogs.com/walkingboy/archive/2010/08/11/linq-to-reflection.html,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
存储 Java API
Java中的Reflection(反射)、暴力反射
Java中的Reflection(反射)、暴力反射
|
5月前
|
存储 Java API
C#反射(Reflection)详解
反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。反射指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗一点:我们在获取其他实体类的字段名或实列,只能获取公有的,而有了反射之后可以获取私有的,可以获取他的基类等等,可以说把家底查得清清楚楚。
31 1
|
7月前
|
Java 关系型数据库 MySQL
C#反射(Reflection)详解及于java反射的对比
C#反射(Reflection)详解及于java反射的对比
|
8月前
|
设计模式 安全 Java
反射(reflection)详细讲解
反射(reflection)详细讲解
70 0
|
Java API
20 Java 使用反射(Reflection) 和内省技术
反射(Reflection)是程序的自我分析能力,通过反射可以确定类有哪些方法、有哪些构造方法以及有哪些成员变量。Java语言提供了反射机制,通过反射机制能够动态读取一个类的信息;能够在运行时动态加载类,而不是在编译期。反射可以应用于框架开发,它能够从配置文件中读取配置信息动态加载类、创建对象,以及调用方法和成员变量。
107 0
|
开发框架 自然语言处理 .NET
Linq To Object——三种委托
Linq To Object——三种委托
104 0