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去查询并获取单一的方法、属性,字段,总211.html">觉得还是要写非常多的代码。要先.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

时间: 2024-10-31 12:26:46

LINQ TO Reflection的相关文章

同一个超类的方法执行问题base

问题描述 [color=#FF0000]代码虽然长,但是很简单,高手帮看下.问题是ld.Show()方法执行后为啥会执行xz,cy的Show方法?好像和base有关,base不是执行完超类的方法就该结束吗,为啥还要执行xz和cy的show?越详细越好usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Text;usingSystem.Threading.Ta

很变态的反射问题。虚心请教

问题描述 我需要反射获取一个类的私有方法..但这个私有方法是有方法重载的..当然,这也不是问题,我们能从外部执行方法参数的个数和类型来获取..但问题来了..这个方法的参数的类型有可能是泛型的..这下怎么办?publicclasstest{privatevoidSave<T>(Tt,stringa){}privatevoidSave<T>(inta){}}publicclassrun{publicvoidSave<T>(Tt){//这样可以获得privatevoidSav

第一次很认真很认真的做一件事,但是就卡在这里了,找了很多方法都没有成功,最后的希望全在这里了,希望好心人帮忙解决一些,您的几分钟有可能解决我几天都解决不了的问题

问题描述 我们学校的教务在线是gbk解码,但wp不支持,网上说用getGDCCEcoding可以解决,但在wp上报"System.Type"不包含"Assembly"的定义,并且找不到可接受类型为"System.Type"的第一个参数的扩展方法"Assembly"(是否缺少using指令或程序集引,第一次很认真的学习一门技术,希望有好心人帮忙解决,有可能您花上几分钟的事,可能解决困恼我好几天都解决不了的问题 解决方案 解决方案

关于c#动态调用非托管DLL的内存释放问题

问题描述 本人由于客户的需要,需要在程序的运行过程中,动态加载不同的DLL.这与直接调用非托管DLL不一样.下面这个帖子中的第三个方法很好的说明了如何动态调用非托管DLL.http://blog.csdn.net/pansiom/article/details/568096#comments为了方便使用,我把文中的方法弄成了一个DLDApi类,如下usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Re

使用Attribute+Reflection来提高代码重用

这篇文章两个目的,一是开阔设计的思路,二是实例代码可以拿来就用. 设计的思路来源于<Effective c#>第一版Item 24: 优先使用声明式编程而不是命令式编程.特别 的地方是,希望提供多个属性的默认排序,而不仅仅只根据一个属性,另外一点是,优先调用对象属性 实现了的IComparable<T>接口,如果没有实现接口,才调用IComparable进行比较.排序类实现 泛型,得到类型安全. 总的思路:Attribute用来装饰我们想要获取元数据的类,使用Reflection来

LINQ to SQL实现数据访问通用基类(续)

在我们基于Domain驱动模式开发面向对象的多层架构的时候,层和层之间数据的传输对象(DTO)往往 简化为领域对象模型,在上文中就是我们利用LINQ TO SQL对象设计器生成的Bill,Customer等实体类. 存在的问题 通常的做法,我们把这些实体类单独分成一层,这样程序分层划分成如下: 数据访问层(Data Access Layer) 业务层 (Business Layer) 用户界面层(UI Layer) 实体层(Entity Layer) 注意,多层应用程序,一般遵守这样的规则:UI

Linq To SQL下实现动态表名的映射

提出问题 前段时间,在博客园里看到有位朋友,问如何实现在动态表名.我们都知道,把一个实体类映谢到表 里,应该这样写: [Table(Name = "User")] class User { [Column] public int ID; [Column] public string Name; } 很明显,这里的表名是写死的,有些时候,我们可能要根据不同的情况实现不同的表名 里加个前缀或者后缀,例如: tt_User,aa_User,User1.User2. 分析问题 要解决这个问题,

使用Linq实现强类型反射

今天无意中看到这一篇文章Linq beyond queries: strong-typed reflection,发现Linq除了查询还 可以用于其它方面,这篇文章里面主要介绍了如何通过Linq来实现强类型的反射. 通常在使用反射的时候,如果不小心把方法名称写错或者参数类型不匹配,运行时就会抛出异常.一 般来说我们会这样写代码来获得MethodInfo: MethodInfo mi = typeof(MyTest).GetMethod("TestFunc",new Type[]{ ty

Linq Lambda表达式全面分析

在向大家详细介绍Linq Lambda表达式之前,首先让大家了解下expr是什么样的东西,然后全面介绍 Linq Lambda表达式. 介绍Linq Lambda表达式之前,先看一个例子: Expression<Func<string, bool>> expr = o => o.Length > 10; 初次接触Linq Lambda表达式的人可能会被搞迷糊,这样的语句到底是什么意思,怎么样工作,原理又 是什么. 逐级分析以上语句,分为两个部分,以等号为界. 第一部分是