2012-12-06 6 views
4

속성 표현식을 사용하여 비슷한 구문을 갖는 속성 값을 다음과 같이 변수를 전달하는 데 사용하도록하는 최종 목적의 코드가 있습니다. out 또는 ref 매개 변수 의 라인을 따라속성 표현식에서 속성 소유 객체 가져 오기

뭔가 :

public static foo(()=>Object.property, value); 

그리고 Object.Property 값의 값이 할당됩니다. 그래서이

public static object GetOwningObject<T>(this Expression<Func<T>> @this) 
    { 
     var memberExpression = @this.Body as MemberExpression; 
     if (memberExpression != null) 
     { 
      var fieldExpression = memberExpression.Expression as MemberExpression; 
      if (fieldExpression != null) 
      { 
       var constExpression = fieldExpression.Expression as ConstantExpression; 
       var field = fieldExpression.Member as FieldInfo; 
       if (constExpression != null) if (field != null) return field.GetValue(constExpression.Value); 
      } 
     } 
     return null; 
    } 

, 같은 속성 식() => Object.Property에 사용하는 경우, 인스턴스를 돌려 줄 것입니다 :

나는 재산의 owining 객체를 얻기 위해 다음 코드를 사용하고 있습니다 의 '개체'. 저는 속성 표현식을 사용하는 것에 다소 익숙하며, 여러 가지 방법으로 구현하고 있지만, 지금까지 가지고있는 것을 확장하여() => Foo.Bar.Baz와 같은 표현식을 얻고 싶습니다. Foo가 아니라 Bar에게 줄 것이다. 항상 표현식에 마지막으로 포함 된 객체가 필요합니다.

아이디어가 있으십니까? 미리 감사드립니다.

답변

1

당신이해야 할 일은 속성 체인을 통해 가장 바깥 쪽 개체로 이동하는 것입니다. 아래 샘플은 오히려 자기 설명하고 확장 메서드는 속성뿐만 아니라 체인 필드에 일 것이라는 점을 보여줍니다 : 나는 이러한 모든 년 전 놓친

class Foo 
{ 
    public Bar Bar { get; set; } 
} 

class Bar 
{ 
    public string Baz { get; set; } 
} 

class FooWithField 
{ 
    public BarWithField BarField; 
} 

class BarWithField 
{ 
    public string BazField; 
} 

public static class LambdaExtensions 
{ 
    public static object GetRootObject<T>(this Expression<Func<T>> expression) 
    { 
     var propertyAccessExpression = expression.Body as MemberExpression; 
     if (propertyAccessExpression == null) 
      return null; 

     //go up through property/field chain 
     while (propertyAccessExpression.Expression is MemberExpression) 
      propertyAccessExpression = (MemberExpression)propertyAccessExpression.Expression; 

     //the last expression suppose to be a constant expression referring to captured variable ... 
     var rootObjectConstantExpression = propertyAccessExpression.Expression as ConstantExpression; 
     if (rootObjectConstantExpression == null) 
      return null; 

     //... which is stored in a field of generated class that holds all captured variables. 
     var fieldInfo = propertyAccessExpression.Member as FieldInfo; 
     if (fieldInfo != null) 
      return fieldInfo.GetValue(rootObjectConstantExpression.Value); 

     return null; 
    } 
} 

[TestFixture] 
public class Program 
{ 
    [Test] 
    public void Should_find_root_element_by_property_chain() 
    { 
     var foo = new Foo { Bar = new Bar { Baz = "text" } }; 
     Expression<Func<string>> expression =() => foo.Bar.Baz; 
     Assert.That(expression.GetRootObject(), Is.SameAs(foo)); 
    } 

    [Test] 
    public void Should_find_root_element_by_field_chain() 
    { 
     var foo = new FooWithField { BarField = new BarWithField { BazField = "text" } }; 
     Expression<Func<string>> expression =() => foo.BarField.BazField; 
     Assert.That(expression.GetRootObject(), Is.SameAs(foo)); 
    } 
} 
+0

죄송합니다! 나는 이것을 시도 할 것이지만, 그 코드는 오래 전에 사라졌지 만 그것은 나에게 좋을 것 같다. – Brandorf