比系统高效的简单反射类,大家给点意见

jy02305022 2011-04-14 01:34:42
类名:EasyReflect
功能:反射类的属性,字段和方法的返回值

演示(1):

//委托调用:
//方法名GetPropertyValue,参数,1.类类型,2.需要反射的属性名(string)
//返回一个委托ReflectDelegate ,参数object,返回值 object
ReflectDelegate reflect = EasyReflect.GetPropertyValue(typeof(Test), "Text");
Test test = new Test();//测试类
object value = reflect(test);//获得测试类的Text属性的值(object类型)

演示(2):

//直接调用:
Test test = new Test();//测试类
object value = EasyReflect.GetPropertyValue(typeof(Test), "Text")(test);



下面是系统的反射方法
演示(1):

//委托调用:
MethodInfo method = typeof(Test).GetProperty("Text", EasyIL.ALLATTR).GetGetMethod();//获得属性的Get方法
ReflectDelegate reflect2 = delegate(object test1) { return method.Invoke(test1, null); };//获得invoke方法委托
Test test = new Test();//测试类
object value = reflect(test);//获得测试类的Text属性的值(object类型)

演示(2):

//直接调用:
Test test = new Test();//测试类
object value = typeof(Test).GetProperty("Text", EasyIL.ALLATTR).GetGetMethod().Invoke(test, null);



然后是性能测试
演示{1}

//委托方式调用10个100W次,建立委托时间不算在内
ReflectDelegate reflect = EasyReflect.GetPropertyValue(typeof(Test), "Text");
MethodInfo method = typeof(Test).GetProperty("Text", EasyIL.ALLATTR).GetGetMethod();
ReflectDelegate reflect2 = delegate(object test1) { return method.Invoke(test1, null); };

Test test = new Test();//测试类
Stopwatch sw = new Stopwatch();//系统类:提供一组方法和属性,可用于准确地测量运行时间。
object value;
for (int i = 0; i < 10; i++)
{
sw.Reset();//重置测量时间
sw.Start();//开始计时
for (int j = 0; j < 100000; j++)
{
value = reflect(test);//使用EasyReflect建立的委托
}

sw.Stop();//停止即使
Console.Write(sw.ElapsedMilliseconds + " ms \t\t");//打印时间
sw.Reset();//重置测量时间
sw.Start();//开始计时
for (int j = 0; j < 100000; j++)
{
value = reflect2(test);//使用系统建立的委托
}
sw.Stop();//停止即使
Console.WriteLine(sw.ElapsedMilliseconds + " ms");//打印时间
}
Console.Read();


结果如下:
20 ms 365 ms
2 ms 362 ms
2 ms 364 ms
2 ms 361 ms
2 ms 360 ms
2 ms 361 ms
2 ms 361 ms
2 ms 365 ms
2 ms 367 ms
2 ms 367 ms

测试{2}

//直接使用反射调用10个100W次
Test test = new Test();//测试类
Stopwatch sw = new Stopwatch();//系统类:提供一组方法和属性,可用于准确地测量运行时间。
object value;
for (int i = 0; i < 10; i++)
{
sw.Reset();//重置测量时间
sw.Start();//开始计时
for (int j = 0; j < 100000; j++)
{//使用EasyReflect类直接反射
value = EasyReflect.GetPropertyValue(typeof(Test), "Text")(test);
}

sw.Stop();//停止即使
Console.Write(sw.ElapsedMilliseconds + " ms \t\t");//打印时间
sw.Reset();//重置测量时间
sw.Start();//开始计时
for (int j = 0; j < 100000; j++)
{//使用系统直接反射
value = typeof(Test).GetProperty("Text", EasyIL.ALLATTR).GetGetMethod().Invoke(test, null);
}
sw.Stop();//停止即使
Console.WriteLine(sw.ElapsedMilliseconds + " ms");//打印时间
}
Console.Read();


结果如下:
60 ms 485 ms
35 ms 476 ms
34 ms 479 ms
34 ms 483 ms
33 ms 475 ms
34 ms 476 ms
33 ms 478 ms
34 ms 479 ms
35 ms 479 ms
33 ms 481 ms




====================================================================================
简单介绍
类主要是靠参数实现写用IL中间码写一个动态方法而实现的
实现过程中有一些问题:
问题1
动态方法初始化过程太长,写一个动态方法,其效率会比直接反射更低
解决方法:使用委托,初始化之后直接使用委托调用,不用再次写动态方法
问题2
第一次初始化时间太长,效率会直接反射更低,而且很多
解决方法:
第一次初始化直接使用系统的反射方法建立一个委托,然后开启一个线程初始化动态方法
当线程结束时候,修改委托指向方法,也就是说,在初始化完成之后再调用这个委托实际是调用了
动态方法,所以速度要快快,,,再快
问题3
如果使用EasyReflect直接反射,其实每次还是在初始化,只是开了一个线程
这样如果是重复的调用,其实是不用一直初始化的
所以又加上了一个类内部的缓存,来保存曾经初始化过的委托
还会根据使用调整顺序,如果缓存满(20~50可设置),则删除最远一次使用过的缓存
...全文
628 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
「已注销」 2011-04-14
  • 打赏
  • 举报
回复
现在在公司 不能上论坛 用手机上的 大家先给我点意见 我完善一下 晚上回去就发源码
「已注销」 2011-04-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 fangxinggood 的回复:]

哦。它的效率应该比上面创建的系统委托更好些

PS: EasyReflect.GetPropertyValue 的实现可以贴出来show一下。

不过要说快,应该还是IL Emit最快吧,不过IL的语法及检查是件头痛的事。
现在有了lambda,用lambda expression来构造一个属性代理应该是个不错的选择。
[/Quote]

我这个就是IL写的
机器人 2011-04-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 caozhy 的回复:]
《C# Effective C#》大力推荐用表达式API取代反射。
[/Quote]
恩,前几天还纠结于能否用expression来构造一个强类型的匿名类,就像linq的select("A")这样。
后来想通了,要想强类型必需指定T,除了IL没别的办法了。linq的Dynamic类结局也是用IL。
@__@

这里有份老赵写的 FastReflectionLib 分享下:
http://download.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=fastreflectionlib&DownloadId=56272&FileTime=128774550182200000&Build=17748
  • 打赏
  • 举报
回复
有点高深
threenewbee 2011-04-14
  • 打赏
  • 举报
回复
建议lz提供下载。
threenewbee 2011-04-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 fangxinggood 的回复:]
哦。它的效率应该比上面创建的系统委托更好些

PS: EasyReflect.GetPropertyValue 的实现可以贴出来show一下。

不过要说快,应该还是IL Emit最快吧,不过IL的语法及检查是件头痛的事。
现在有了lambda,用lambda expression来构造一个属性代理应该是个不错的选择。
[/Quote]
+1

《C# Effective C#》大力推荐用表达式API取代反射。
机器人 2011-04-14
  • 打赏
  • 举报
回复
哦。它的效率应该比上面创建的系统委托更好些

PS: EasyReflect.GetPropertyValue 的实现可以贴出来show一下。

不过要说快,应该还是IL Emit最快吧,不过IL的语法及检查是件头痛的事。
现在有了lambda,用lambda expression来构造一个属性代理应该是个不错的选择。
「已注销」 2011-04-14
  • 打赏
  • 举报
回复
LS 你这个必须绑定到特定的 实例对象属性 或者绑定 静态属性
我的做法是一个委托.通过传入的实例对象不同 反射出不同对象的属性结果
不一样的
「已注销」 2011-04-14
  • 打赏
  • 举报
回复
GetPropertyValue实现代码如下


/// <summary>
/// 获取一个获取属性的值的委托
/// </summary>
/// <param name="classType">需要获取属性的类</param>
/// <param name="propertyName">属性名称</param>
public static ReflectGet GetPropertyValue(Type classType, string propertyName)
{
string cacheKey = classType.FullName + SPACE + propertyName;//缓存标识符key
ReflectGet returnDelegate; //声明返回委托对象
if (cacheGet.TryGetValue(cacheKey, out returnDelegate)) //取出缓存中的委托,如果没有返回false
{
return returnDelegate; //如果有,直接返回该委托
}
cacheGet.Add(cacheKey, returnDelegate); //添加到缓存

ReflectGet reflectGet; //声明实际引用的委托

reflectGet = delegate(object obj) //使用系统反射方法
{
return classType.GetProperty(propertyName, EasyIL.ALLATTR).GetGetMethod().Invoke(obj, null);
};

//开启新线程初始化动态方法
ThreadPool.QueueUserWorkItem(delegate(object o)
{
//Type returnType = classType.GetProperty(propertyName, EasyIL.ALLATTR).PropertyType;
Type returnType = typeof(object); //设置返回值类型
Type argType = typeof(object); //设置参数类型

EasyIL il = new EasyIL(returnType, classType.Module, argType); //建立简单EasyIL对象
//EasyIL:自定义类,用于简单操作IL生成器生成动态方法

//ILParameterBase obj = il.Convert(classType, il["0"]); //将参数0转换为
PropertyInfo propertyInfo =
classType.GetProperty(propertyName, EasyIL.ALLATTR); //获得属性对象PropertyInfo
ILProperty objProperty =
il.CreateProperty(propertyInfo, il["0"]); //根据对象和属性对象 创建IL参数
//il[0]表示第0个参数的ILProperty形式,ILProperty:自定义类,用于在EasyIL中代表一个参数
il.Return(objProperty); //return 属性的值
//Type delegateType = typeof(delegateGeneric<,>).MakeGenericType(returnType, classType);
reflectGet = (ReflectGet)il.CreateDelegate(typeof(ReflectGet)); //返回一个委托

});

returnDelegate = delegate(object obj) { return reflectGet(obj); }; //给返回委托赋值
return returnDelegate;
}
机器人 2011-04-14
  • 打赏
  • 举报
回复
ReflectDelegate reflect2 = delegate(object test1) { return method.Invoke(test1, null); };

改为:

Func<object> reflect2 = (Func<object>)Delegate.CreateDelegate(typeof(Func<object>), test1, method);

因为你的委托里实际还是反射。不如直接创建属性的委托快。

http://www.cnblogs.com/artech/archive/2011/03/26/Propertyaccesstest.html

110,545

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧