任意两个对象,对他们存在相同的字段赋值,字段包括普通property,其他类对象,父类的property。由于是任意对象,不知道类型
,因此一般的做法是直接调用反射,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