任意两个对象赋值,用Spring.Objects.ObjectWrapper效率比直接反射还慢?
时间:2010-12-25 来源:Lawson
,因此一般的做法是直接调用反射,spring.net内部封装了任意对象赋值的方法,但是经过我的测试,发现它的速度比直接反射还慢,不知
道是自己哪里没有优化,还是方法执行有问题,粗略看了一下spring.net内部源代码,发现它自己实现了表达式树和AST来解析它的包装对象,
没太看明白,如果有谁之前研究过,可以分享一些技术文章出来。
本次用直接反射,Spring.net的ObjectWrapper和jeffreyzhao的FastReflectionLib http://www.codeplex.com/FastReflectionLib进行赋值的
效率比较。
直接反射代码如下:
直接反射代码 /// <summary>/// 把原始对象的值赋值给目标对象
/// </summary>
/// <param name="originObj">原始对象</param>
/// <param name="targetObj">目标对象</param>
public static void Fill(object originObj, object targetObj)
{
PropertyInfo[] properties = originObj.GetType().GetProperties();
foreach (PropertyInfo item in properties)
{
PropertyInfo property = targetObj.GetType().GetProperty(item.Name);
try
{
property.SetValue(targetObj, item.GetValue(originObj, null), null);
}
catch
{
continue;
}
}
}
Spring.net用ObjectWrapper实现赋值代码如下:
Spring.net /// <summary>/// 把原始对象的值赋值给目标对象
/// </summary>
/// <param name="originObj">原始对象</param>
/// <param name="targetObj">目标对象</param>
public static void Fill<O,T>(object originObj, object targetObj)
{
ObjectWrapper ow = new ObjectWrapper(originObj);
ObjectWrapper tw = new ObjectWrapper(targetObj);
PropertyInfo[] properties = ow.GetPropertyInfos();
foreach (PropertyInfo item in properties)
{
try
{
tw.SetPropertyValue(item.Name, ow.GetPropertyValue(item.Name));
}
catch
{
continue;
}
}
}
用FastReflectionLib实现赋值代码如下:
FastReflectionLib /// <summary>/// 把原始对象的值赋值给目标对象
/// </summary>
/// <param name="originObj"></param>
/// <param name="targetObj"></param>
public static void Fill(object originObj, object targetObj)
{
PropertyInfo[] properties = originObj.GetType().GetProperties();
foreach (PropertyInfo item in properties)
{
PropertyInfo property = targetObj.GetType().GetProperty(item.Name);
try
{
property.FastSetValue(targetObj, item.FastGetValue(originObj));
}
catch
{
continue;
}
}
}
为了让任意对象更加真实性,我的两个对象将继承一个类,并且对象中还包括其他对象,对象具体内容就不展现出来了,最下面提供源代
码下载,感兴趣的可以下载试试,如果有什么好的建议,不忘了告诉我一下。
测试代码如下:
测试代码 static void Main(string[] args){
var origin = new SourceObject() { Id = 2, Name = "lawson", Url = "http://lawson.cnblogs.com", CreateTime = new DateTime(2000, 10, 10), baseStr = "1base", otherO = new OtherObj() { others="other object others"} };
var target = new TargetObject() { Id = 3, Name = "aa", Url = "http://www.cnblogs.com", CreateTime = new DateTime(2010, 10, 1) };
int time = 10000;
Stopwatch stopwatch4 = Stopwatch.StartNew();
for (int i = 0; i < time; i++)
{
target.Id = origin.Id;
target.Name = origin.Name;
target.Url = origin.Url;
target.CreateTime = origin.CreateTime;
}
Console.WriteLine(string.Format("直接赋值耗时:{0} 毫秒", stopwatch4.ElapsedMilliseconds));
Stopwatch stopwatch2 = Stopwatch.StartNew();
for (int i = 0; i < time; i++)
{
DirectReflect.Exchanger.Fill(origin, target);
}
Console.WriteLine(string.Format("直接反射赋值耗时:{0} 毫秒", stopwatch2.ElapsedMilliseconds));
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < time; i++)
{
SpringNet.Exchanger.Fill<SourceObject, TargetObject>(origin, target);
}
Console.WriteLine(string.Format("Springnet赋值耗时:{0} 毫秒", stopwatch.ElapsedMilliseconds));
Stopwatch stopwatch3 = Stopwatch.StartNew();
for (int i = 0; i < time; i++)
{
FastReflect.Exchanger.Fill(origin, target);
}
Console.WriteLine(string.Format("FastReflect赋值耗时:{0} 毫秒", stopwatch3.ElapsedMilliseconds));
Console.ReadKey();
}
在Release编译运行下的结果如下:
直接赋值耗时:0 毫秒
直接反射赋值耗时:187 毫秒
Springnet赋值耗时:3642 毫秒
FastReflect赋值耗时:133 毫秒
在我的测试中,Springnet的ObjectWrapper和直接反射或者FastReflect比较中,性能完全不是一个数量级的。
下面提供我的测试代码下载
/Files/Lawson/ExchangeValue-lawson.rar