2017-12-06 26 views
0

두 번째 매개 변수를 사용하여 문자열과 반사를 사용하지 않고 개체의 속성을 얻을 수 있도록 메서드에 개체와 두 번째 매개 변수를 입력 할 수 있습니까? 이 속성을 사용하여 값을 읽고 쓸 수 있습니까?값 대신에 속성을 가져 오는 Func 함수

내가 사용할 수있는 아래의 두 가지 방법을 작성했지만 각각 하나의 단점이 있습니다. 첫 번째 DoStuff는 typesafe ("good")이지만 세 개의 매개 변수 ("bad")가 필요합니다. 두 번째 매개 변수는 두 개 (최적)의 매개 변수가 필요하지만 속성을 지정하는 문자열에 의존하기 때문에 형식 안됨 ("불량")이 아닙니다. 어쩌면 내가 생각하지 못했던 Expression을 사용하는 해결책이 있을까요?

배경 : 모든 개체의 가치를 "확장"할 수 있기를 원합니다. (필자의 경우 여러 개체 저장소의 개체 목록이 있으며 이러한 개체는 userid를 문자열로 포함하는 serveral 속성을 가질 수 있습니다. 저장소는 사용자를 conatins 나는

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

void Main() 
{ 
    var x = new Foo { Bar = "hello" }; 
    Console.WriteLine(x.Bar); // prints "hello" 

    // the second paramter (Func<..>) gets the value, the third parameter Action<...>) sets the value 
    DoStuff(x, y => y.Bar, (z, val) => z.Bar = val); 
    Console.WriteLine(x.Bar); // prints "hello goodbye" 

    // just one parameter to get the property, but I would like this to be more type safe, preferably a Func 
    DoStuff2(x, nameof(x.Bar)); 
    Console.WriteLine(x.Bar); // prints "hello goodbye again" 
} 

public void DoStuff<T>(
    T obj, 
    Func<T, string> getProp, 
    Action<T, string> setProp) 
{ 
    var x = getProp(obj); 
    setProp(obj, x + " goodbye"); 
} 

public void DoStuff2<T>(
    T obj, 
    string propName) 
{ 
    var propInfo = typeof(T).GetProperty(propName); 
    var currValue = propInfo.GetValue(obj) as string; 
    propInfo.SetValue(obj, currValue + " again"); 
} 
+2

'Expression >'을 (를) 찾고 있습니다. 컴파일 ('.Compile()')하고 호출하여 값을 가져올 수 있습니다. – john

+0

@john :'Expression >'을 (를) 사용하는'DoStuff3'은 어떻게 생겼을까요? 대답으로 써 주시겠습니까? 아니면 링크가 있습니까? Experssions은 여전히 ​​나에게 조금 혼란 스럽습니다. – mortb

+1

[here] (https://stackoverflow.com/questions/5075484/property-selector-expressionfunct-how-to-get-set-value-to-selected-property)를 참조하십시오.) – john

답변

1

그럼 내가 잠시 전에 그런 일을했던) 이전 저장소에 문자열에 사용자에 대한 정보를 추가 할 수 있습니다. 여기에 예제가 있습니다 :

public void SetValue<T, TP>(T obj, Expression<Func<T, TP>> action, TP value) where T : class 
{ 
     var member = action.Body is UnaryExpression 
       ? ((MemberExpression)((UnaryExpression)action.Body).Operand) 
       : (action.Body is MethodCallExpression 
        ? ((MemberExpression)((MethodCallExpression)action.Body).Object) 
        : (MemberExpression)action.Body); 

    var key = member?.Member.Name; 
    typeof(T).GetProperty(key).SetValue(obj, value); 

} 

당신은 이것을 이렇게 부릅니다.

SetValue<User>(x=> x.UserName, "Admin"); 
+2

'this [key] '표현식은이 코드가 복사 된 클래스에 더 많은 것이 있음을 보여줍니다. – mortb

+0

아니요. 당신은 typeof (T) .GetProperty (key) .SetValue()가 필요합니다. –

+0

라이브러리를 원하면 https://www.nuget.org/packages/Generic.LightDataTable/ –