2012-04-17 75 views
7

我的項目中有一些單元測試,我們希望能夠設置一些具有私人設置器的屬性。如何通過lambda表達式傳遞屬性?

public static void SetPrivateProperty(this object sourceObject, string propertyName, object propertyValue) 
{ 
    sourceObject.GetType().GetProperty(propertyName).SetValue(sourceObject, propertyValue, null); 
} 

假設我有一個像這樣的的TestObject:

public class TestObject 
{ 
    public int TestProperty{ get; private set; } 
} 

然後我可以在我的單元測試調用此如下:目前我通過反射和這個擴展方法做

myTestObject.SetPrivateProperty("TestProperty", 1); 

但是,我想在編譯時驗證屬性名稱,因此我希望能夠通過通過表達式的屬性,如下所示:

myTestObject.SetPrivateProperty(o => o.TestProperty, 1); 

我該怎麼做?

+0

什麼是lambda表達式的目的是什麼?提供編譯時驗證? – mellamokb 2012-04-17 14:46:39

+0

@mellamokb是的。如果還有其他方法可以做到這一點,我就是遊戲。 – Sterno 2012-04-17 14:47:06

+0

請參閱http://stackoverflow.com/questions/671968/retrieving-property-name-from-lambda-expression – phoog 2012-04-17 14:49:53

回答

9

如果吸氣劑是公共的,那麼以下應該起作用。它會給你一個看起來像這樣的擴展方法:

var propertyName = myTestObject.NameOf(o => o.TestProperty); 

它需要一個公共的getter。我希望在某種程度上,像這樣的反射功能可以融入語言中。

public static class Name 
{ 
    public static string Of(LambdaExpression selector) 
    { 
     if (selector == null) throw new ArgumentNullException("selector"); 

     var mexp = selector.Body as MemberExpression; 
     if (mexp == null) 
     { 
      var uexp = (selector.Body as UnaryExpression); 
      if (uexp == null) 
       throw new TargetException(
        "Cannot determine the name of a member using an expression because the expression provided cannot be converted to a '" + 
        typeof(UnaryExpression).Name + "'." 
       ); 
      mexp = uexp.Operand as MemberExpression; 
     } 

     if (mexp == null) throw new TargetException(
      "Cannot determine the name of a member using an expression because the expression provided cannot be converted to a '" + 
      typeof(MemberExpression).Name + "'." 
     ); 
     return mexp.Member.Name; 
    } 

    public static string Of<TSource>(Expression<Func<TSource, object>> selector) 
    { 
     return Of<TSource, object>(selector); 
    } 

    public static string Of<TSource, TResult>(Expression<Func<TSource, TResult>> selector) 
    { 
     return Of(selector as LambdaExpression); 
    } 
} 

public static class NameExtensions 
{ 
    public static string NameOf<TSource, TResult>(this TSource obj, Expression<Func<TSource, TResult>> selector) 
    { 
     return Name.Of(selector); 
    } 
}