Func获取属性而不仅仅是值

时间:2017-12-06 09:18:06

标签: c# expression-trees func

是否可以向方法输入对象和第二个参数,以便可以使用第二个参数(不使用字符串和反射)来获取对象的属性并使用该属性来读取和写入值?

我在下面写了两种方法,我可以使用,但每种方法都有缺点。第一个DoStuff是类型安全的(“好”)但它需要三个参数(“坏”)。第二个需要两个参数(最佳),但它不是类型安全(“坏”),因为它依赖于一个字符串来指定属性。也许使用Expression有一些我没有想到的解决方案?

背景:用例是我希望能够“扩展”任何对象的值(在我的例子中,我有来自多个对象存储库的对象列表,这些对象可能有多个包含用户ID作为字符串的属性。另一个存储库同意用户,我想将有关用户的信息添加到以前存储库中的字符串中)

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");
}

1 个答案:

答案 0 :(得分: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");