对象属性之间的相互赋值

(一)前言

当不同命名空间下的两个类具有相同的属性,并且需要进行相互赋值时,如下图中的Jasen.Core.Info类的实例与Jasen.Core.Test.Info类的实例需要相互赋值时,按照一般的思路直接赋值就可以了。通常,这种情况在调用Web Service的时候比较常见。当需要转换的类很多时,亦或者需要转换的属性很多时,我们就需要根据一定的规则来对这种场景来进行设计了,谁也不会傻布拉吉的一个一个属性的去给对象赋值。

 

 

 (二)ObjectMapper 类负责对象之间相对应的属性间的赋值

 1 /// <summary>
 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类如下:

 1 /// <summary>
 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             }

 (三)单元测试

 1         [TestMethod()]
 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>关系了。

 

posted @ 2011-03-31 23:58  jasen.kin  阅读(5662)  评论(6编辑  收藏  举报