对象属性之间的相互赋值
(一)前言
当不同命名空间下的两个类具有相同的属性,并且需要进行相互赋值时,如下图中的Jasen.Core.Info类的实例与Jasen.Core.Test.Info类的实例需要相互赋值时,按照一般的思路直接赋值就可以了。通常,这种情况在调用Web Service的时候比较常见。当需要转换的类很多时,亦或者需要转换的属性很多时,我们就需要根据一定的规则来对这种场景来进行设计了,谁也不会傻布拉吉的一个一个属性的去给对象赋值。
(二)ObjectMapper 类负责对象之间相对应的属性间的赋值
2 ///
3 /// </summary>
4 public class ObjectMapper
5 {
6 /// <summary>
7 ///
8 /// </summary>
9 /// <param name="sourceType"></param>
10 /// <param name="targetType"></param>
11 /// <returns></returns>
12 public static IList<PropertyMapper> GetMapperProperties(Type sourceType, Type targetType)
13 {
14 var sourceProperties = sourceType.GetProperties();
15 var targetProperties = targetType.GetProperties();
16
17 return (from s in sourceProperties
18 from t in targetProperties
19 where s.Name == t.Name && s.CanRead && t.CanWrite && s.PropertyType == t.PropertyType
20 select new PropertyMapper
21 {
22 SourceProperty = s,
23 TargetProperty = t
24 }).ToList();
25 }
26
27 /// <summary>
28 ///
29 /// </summary>
30 /// <param name="source"></param>
31 /// <param name="target"></param>
32 public static void CopyProperties(object source, object target)
33 {
34 var sourceType = source.GetType();
35 var targetType = target.GetType();
36 var mapperProperties = GetMapperProperties(sourceType, targetType);
37
38 for (int index = 0,count=mapperProperties.Count; index < count; index++)
39 {
40 var property = mapperProperties[index];
41 var sourceValue = property.SourceProperty.GetValue(source, null);
42 property.TargetProperty.SetValue(target, sourceValue, null);
43 }
44 }
45 }
public static void CopyProperties(object source, object target)方法将源对象的属性值赋给目标对象的属性。其中必须满足以下条件:s.Name == t.Name && s.CanRead && t.CanWrite && s.PropertyType == t.PropertyType,也就是两个对象之间赋值的属性名,属性类型必须相同,而且源对象的属性必须可读,目标对象的属性可写。
public static IList<PropertyMapper> GetMapperProperties(Type sourceType, Type targetType)方法通过LINQ将源对象和目标对象相对应的属性对放置在List<PropertyMapper>集合中,每一个PropertyMapper对应一个SourceProperty和TargetProperty。PropertyMapper类如下:
2 ///
3 /// </summary>
4 public class PropertyMapper
5 {
6 /// <summary>
7 ///
8 /// </summary>
9 public PropertyInfo SourceProperty
10 {
11 get;
12 set;
13 }
14
15 /// <summary>
16 ///
17 /// </summary>
18 public PropertyInfo TargetProperty
19 {
20 get;
21 set;
22 }
23 }
最后循环来遍历List<PropertyMapper>集合,通过反射进行赋值,主要代码如下:
for (int index = 0,count=mapperProperties.Count; index < count; index++)
39 {
40 var property = mapperProperties[index];
41 var sourceValue = property.SourceProperty.GetValue(source, null);
42 property.TargetProperty.SetValue(target, sourceValue, null);
43 }
(三)单元测试
2 public void CopyPropertiesTest()
3 {
4 Jasen.Core.Info source = new Jasen.Core.Info()
5 {
6 Name = "jasen",
7 CreateTime = "2011-3-31".AsDateTime(),
8 Exist = true,
9 ConflictOption = ConflictOption.OverwriteChanges
10 };
11 Info target = new Info();
12 ObjectMapper.CopyProperties(source, target);
13
14 Assert.AreEqual(source.ConflictOption,target.ConflictOption);
15 Assert.AreEqual(source.CreateTime, target.CreateTime);
16 Assert.AreEqual(source.Exist, target.Exist);
17 Assert.AreEqual(source.Name, target.Name);
18 }
(四)其他
当然,当需要转换的对象很多时,可以采用字典Dictionary来提高性能,Dictionary主要用来保存对象对应属性间的List<PropertyMapper>关系,当下次再次调用时候就不需要再次获取对象对应属性间的List<PropertyMapper>关系了。