2015-12-21 100 views
0

爲WPF綁定問題,我試圖找出我怎樣才能在蘭巴表達式被傳遞給一個對象實例的引用。如何獲取通過lambda表達式傳遞的對象實例的引用?

我已經創建了新的類別「CustomBinding」」 thta可以採取一個lambda表達式作爲參數,從中提取的源和路徑。這種運作良好,如果是 正在傳遞的拉姆達有它的參考同一呼叫者類中的屬性:

public class CustomBinding : Binding 
{ 
    public CustomBinding(Expression<Func<object>> expr) : base() 
    { 
     Source = (expr.Compile().Target as Closure).Constants[0]; 
     Path = (expr.Body as MemberExpression).Member.Name; 
    } 
} 


public class A 
{ 
    public string MyProperty { get;set;} 

    public void MyMethod() 
    { 
     var workingbinding = new CustomBinding(()=>MyProperty); 
     ..... 
    } 
} 

但是,如果lambda表達式使用另一個對象的屬性是什麼。我如何獲得該對象的引用?

像這樣:

public class B 
{ 
    public void MyOtherMethod() 
    { 
     var otherObject = new A(); 
     var nonworkingbinding = new CustomBinding(() => otherObject.MyProperty) 
       //this fails, the Source is not set correct 
    } 
} 

我怎樣才能提取lambda表達式的 「otherObject」 實例的引用?

+0

如果有什麼在使用中沒有對象?調用'CustomBinding'就像這樣'CustomBinding(()=> new object())'是合法的。在這種情況下,你會期望'引用傳遞對象'嗎? – Michael

回答

3

爲objectName.PropertyName最簡單的方法:

public static object GetContainer<T>(Expression<Func<T>> propertyLambdaExpression) 
{ 
    return Evaluate((propertyLambdaExpression.Body as MemberExpression).Expression); 
} 
public static object Evaluate(Expression e) 
{ 
    switch (e.NodeType) 
    { 
     case ExpressionType.Constant: 
      return (e as ConstantExpression).Value; 
     case ExpressionType.MemberAccess: 
      { 
       var propertyExpression = e as MemberExpression; 
       var field = propertyExpression.Member as FieldInfo; 
       var property = propertyExpression.Member as PropertyInfo; 
       var container = propertyExpression.Expression == null ? null : Evaluate(propertyExpression.Expression); 
       if (field != null) 
        return field.GetValue(container); 
       else if (property != null) 
        return property.GetValue(container, null); 
       else 
        return null; 
      } 
     case ExpressionType.ArrayIndex: //Arrays 
     { 
      var arrayIndex = e as BinaryExpression; 
      var idx = (int)Evaluate(arrayIndex.Right); 
      var array = (object[])Evaluate(arrayIndex.Left); 
      return array[idx]; 
     } 
     case ExpressionType.Call: //Generic Lists and Dictionaries 
     { 
      var call = e as MethodCallExpression; 
      var callingObj = Evaluate(call.Object); 
      object[] args = new object[call.Arguments.Count]; 
      for (var idx = 0; idx < call.Arguments.Count; ++idx) 
       args[idx] = Evaluate(call.Arguments[idx]); 
      return call.Method.Invoke(callingObj, args); 
     } 
     default: 
      return null; 
    } 
} 

然後只需調用GetContainer(表達式):

//Get Target Object 
object targetObject = null; 
var memberExp = expr.Body as MemberExpression; 
var bodyExp = memberExp.Expression; 
if (bodyExp != null) 
    targetObject = Expression.Lambda<Func<object>>(bodyExp).Compile()(); 
else if (isStaticProp) 
    targetObject = memberExp.Member.DeclaringType; 
else 
    throw new Exception("Could not determine target object."); 

爲魔鬼的表情像evilObjects [12] .ActualObject.ActualProperty難的方法。

相關問題