2012-11-03 47 views
5

我有2個相同對象的實例o1和o2。如果我正在做的事情如遍歷一個對象並找到非空屬性

if (o1.property1 != null) o1.property1 = o2.property1 

爲對象的所有屬性。循環遍歷對象中的所有屬性並做到這一點最有效的方法是什麼?我看到有人使用PropertyInfo來檢查屬性的nulll,但似乎他們只能通過PropertyInfo集合,但沒有鏈接屬性的操作。

謝謝。

回答

12

可以與反思這樣做:

public void CopyNonNullProperties(object source, object target) 
{ 
    // You could potentially relax this, e.g. making sure that the 
    // target was a subtype of the source. 
    if (source.GetType() != target.GetType()) 
    { 
     throw new ArgumentException("Objects must be of the same type"); 
    } 

    foreach (var prop in source.GetType() 
           .GetProperties(BindingFlags.Instance | 
               BindingFlags.Public) 
           .Where(p => !p.GetIndexParameters().Any()) 
           .Where(p => p.CanRead && p.CanWrite)) 
    { 
     var value = prop.GetValue(source, null); 
     if (value != null) 
     { 
      prop.SetValue(target, value, null); 
     } 
    } 
} 
+0

謝謝,喬恩,完美無缺! – NewDTinStackoverflow

2

從你的例子來看,我認爲你在尋找這樣的事情:

static void CopyTo<T>(T from, T to) 
{ 
    foreach (PropertyInfo property in typeof(T).GetProperties()) 
    { 
     if (!property.CanRead || !property.CanWrite || (property.GetIndexParameters().Length > 0)) 
      continue; 

     object value = property.GetValue(to, null); 
     if (value != null) 
      property.SetValue(to, property.GetValue(from, null), null); 
    } 
} 
+0

我會做出一個通用版本,以保證同一類型的兩個對象的:) – khellang

+0

@khellang偉大的想法:),改變了我的例子 –

+0

偉大的東西! :) – khellang

2

如果你要使用很多次,你可以使用編譯表達式爲更好的性能:

public static class Mapper<T> 
{ 
    static Mapper() 
    { 
     var from = Expression.Parameter(typeof(T), "from"); 
     var to = Expression.Parameter(typeof(T), "to"); 

     var setExpressions = typeof(T) 
      .GetProperties() 
      .Where(property => property.CanRead && property.CanWrite && !property.GetIndexParameters().Any()) 
      .Select(property => 
      { 
       var getExpression = Expression.Call(from, property.GetGetMethod()); 
       var setExpression = Expression.Call(to, property.GetSetMethod(), getExpression); 
       var equalExpression = Expression.Equal(Expression.Convert(getExpression, typeof(object)), Expression.Constant(null)); 

       return Expression.IfThen(Expression.Not(equalExpression), setExpression); 
      }); 

     Map = Expression.Lambda<Action<T, T>>(Expression.Block(setExpressions), from, to).Compile(); 
    } 

    public static Action<T, T> Map { get; private set; } 
} 

而且使用它像這樣:

Mapper<Entity>.Map(e1, e2);