使用表达式通过字符串路径更新嵌套属性值



要解决的问题

我希望能够使用虚构的方法prop更新属性Update。 为此,我想像这样调用该方法:

Root obj = /* ... */;
Update(obj, "sub/sub/prop", "foobar");

例如,我将如何构建一些表达式树来执行此操作?

场景

class Sub2
{
public string prop { get; set; }
}
class Sub1
{
public Sub2 sub { get; set; }
}
class Root
{
public Sub1 sub { get; set; }
}
class Main
{
//...
void Update(object obj, string navigation, object newval) { /* magic */ }
}

完整问题

我需要能够序列化来自某个对象(已解决,方法头public void Serialize<TProperty>(T obj, Stream s, Expression<Func<T, TProperty>> exp)(的单个字段,并在服务器应用程序上更新相应的字段。 只允许更新该字段,某些类嵌套得太深,无法实现诸如"只需使用一些 ID 内容和一个开关,然后将值放入正确的字段中"之类的解决方案,这就是选择这种方法的原因。

可以使用递归向下导航到要更新的属性。这段代码期望路径上的所有属性都不NULL,如果你可以有空值,那么应该很容易有一些检查代码来处理这种情况(抛出异常等(。

void Update(object obj, string navigation, object newval)
{
var firstSlash = navigation.IndexOf("/");
if (firstSlash < 0)
{
obj.GetType().GetProperty(navigation).SetValue(obj, newval);
}
else
{
var header = navigation.Substring(0, firstSlash);
var tail = navigation.Substring(firstSlash + 1);
var subObj = obj.GetType().GetProperty(header).GetValue(obj);
Update(subObj, tail, newval);
}
}

终于解决了我自己

public void Update1(T obj, string[] input, object newval)
{
Type t = typeof(T);
var param1 = Expression.Parameter(t);
Expression exp = param1;
foreach (var it in input.Skip(1).Take(input.Length - 2))
{
var minfo = t.GetProperty(it).GetGetMethod();
exp = Expression.Call(exp, minfo);
t = minfo.ReturnType;
}
var lastprop = t.GetProperty(input.Last());
var minfoset = lastprop.GetSetMethod();
var variableexp = Expression.Variable(lastprop.PropertyType);
exp = Expression.Call(exp, minfoset, variableexp);
var lambda = Expression.Lambda(exp, param1, variableexp);
lambda.Compile().DynamicInvoke(obj, newval);
}

相关内容

  • 没有找到相关文章

最新更新