zoukankan      html  css  js  c++  java
  • 对象属性赋值后续(集合对象的属性赋值)

    (一)前言

    继《对象属性之间的相互赋值 》后,关于集合对象属性的赋值,主要可以通过循环遍历集合中的对象来进行属性间的赋值。这些可以运用于不同对象之间、相关属性类似的情况。最常见的是web services与silverlight之间的对象赋值(对象之间的属性值只有一部分是需要的),这样可以减少silverlight对web services的依赖。

    (二)具体实现

    通过反射将源对象与目标对象之间的属性赋值。源对象的属性名、属性类型必须与目标对象的属性名、属性类型一致,并且源对象的属性必须是可读的,目标对象的属性是可写的(仅针对于需要赋值的属性来说)。具体的源代码如下:

     1     public class ObjectMapper  
     2     {
     3         private static readonly Dictionary<string, IList<PropertyMapper>> _mappers =
     4             new Dictionary<string, IList<PropertyMapper>>();
     5 
     6         public static IList<PropertyMapper> GetMapperProperties(
     7             Type sourceType, Type targetType)
     8         {
     9             var sourceProperties = sourceType.GetProperties();
    10             var targetProperties = targetType.GetProperties();
    11 
    12             return (from s in sourceProperties
    13                     from t in targetProperties
    14                     where s.Name == t.Name && s.CanRead && t.CanWrite && s.PropertyType == t.PropertyType
    15                     select new PropertyMapper
    16                               {
    17                                   SourceProperty = s,
    18                                   TargetProperty = t
    19                               }).ToList();
    20         }
    21 
    22         public static void CopyProperties<T1, T2>(List<T1> sources, List<T2> targets) where T2:new()
    23         {
    24             if (sources == null || sources.Count == 0 || targets == null)
    25             {
    26                 return;
    27             }
    28 
    29             T2 target;
    30             foreach (T1 source in sources)
    31             {
    32                 target = new T2();
    33                 CopyProperties(source, target);
    34                 targets.Add(target);
    35             }
    36         }
    37 
    38         public static void CopyProperties(object source, object target)
    39         {
    40             if (source == null || target == null)
    41             {
    42                 return;
    43             }
    44             var sourceType = source.GetType();
    45             var targetType = target.GetType();
    46             string key = GetMapperKey(sourceType, targetType);
    47             if (!_mappers.ContainsKey(key))
    48             {
    49                 MapperProperties(sourceType, targetType);
    50             }
    51 
    52             var mapperProperties = _mappers[key];
    53 
    54             SetPropertityValue(source, target, mapperProperties);
    55         }
    56 
    57         private static void SetPropertityValue(object source, 
    58             object target, IList<PropertyMapper> mapperProperties)
    59         {
    60             for (int index = 0, count = mapperProperties.Count; index < count; index++)
    61             {
    62                 var property = mapperProperties[index];
    63                 var sourceValue = property.SourceProperty.GetValue(source, null);
    64                 property.TargetProperty.SetValue(target, sourceValue, null);
    65             }
    66         }
    67 
    68         protected static string GetMapperKey(Type sourceType, Type targetType)
    69         {
    70             return string.Format("{0}_{1}", sourceType.FullName,
    71                 targetType.FullName);
    72         }
    73 
    74         public static void MapperProperties(Type source, Type target)
    75         {
    76             if (source == null || target == null)
    77             {
    78                 return;
    79             }
    80 
    81             string key = GetMapperKey(source, target);
    82             if (_mappers.ContainsKey(key))
    83             {
    84                 return;
    85             }
    86 
    87             var properties = GetMapperProperties(source, target);
    88             _mappers.Add(key, properties);
    89         }
    90     }

    有效的方法主要为如下2个:

    (1)第22-36行CopyProperties<T1, T2>(List<T1> sources, List<T2> targets) where T2:new()

    目标对象集合必须添加约束(where T2:new())---必须有默认构造函数。从如下的代码可以看出 target = new T2()必须通过实例化,才能将其添加到目标集合中。

                    T2 target;
    30             foreach (T1 source in sources)
    31             {
    32                 target = new T2();
    33                 CopyProperties(source, target);
    34                 targets.Add(target);
    35             }

    (2)CopyProperties(object source, object target)
    这个方法才是最关键的,因为集合对象之间的赋值主要是通过循环该方法来赋值的。

     

    (三)单元测试

    对象集合对象之间的赋值,相关的单元测试代码如下(仅考虑了简单的对象),通过下面的测试,可以检测到集合对象属性赋值赋值后,值是相同的:

     1         [TestMethod()]
     2         public void CopyPropertiesTest1()
     3         {
     4             List<Jasen.Core.Info> sources = new List<Core.Info>();
     5             for (int index = 0; index < 10; index++)
     6             {
     7                 sources.Add(new Jasen.Core.Info()
     8                 {
     9                     Name = "jasen",
    10                     CreateTime = "2011-5-13".AsDateTime(),
    11                     Exist = true,
    12                     ConflictOption = ConflictOption.OverwriteChanges,
    13                     Index = index
    14                 });
    15             }
    16             List<Info> targets = new List<Info>();    
    17             ObjectMapper.CopyProperties(sources, targets);
    18             for (int index = 0, count = sources.Count; index < count; index++)
    19             {
    20                 Assert.AreEqual(sources[index].ConflictOption, targets[index].ConflictOption);
    21                 Assert.AreEqual(sources[index].CreateTime, targets[index].CreateTime);
    22                 Assert.AreEqual(sources[index].Exist, targets[index].Exist);
    23                 Assert.AreEqual(sources[index].Name, targets[index].Name);
    24                 //Assert.AreEqual(sources[index].Index, targets[index].Index);
    25             }
    26         }

    (四)总结

    以上的代码仅仅针对于简单的属性之间的赋值,对于对象包含IList集合属性的赋值,可以将该IList再进行一次赋值即可。上文中采用字典来使性能提高,当第一次赋值的时候保存需要赋值的相关联的属性对集合。第二次的时候就直接通过键值获取该属性对,不需要再次查找相关的属性对集合。

     

    源代码下载:Jasen.CopyObjectToObjectSample.rar

     

  • 相关阅读:
    Codeforces 1265A Beautiful String
    1039 Course List for Student (25)
    1038 Recover the Smallest Number (30)
    1037 Magic Coupon (25)
    1024 Palindromic Number (25)
    1051 Pop Sequence (25)
    1019 General Palindromic Number (20)
    1031 Hello World for U (20)
    1012 The Best Rank (25)
    1011 World Cup Betting (20)
  • 原文地址:https://www.cnblogs.com/jasenkin/p/copy_source_object_propertities_to_target.html
Copyright © 2011-2022 走看看