作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Expression<Func<IMyclass, int>>
我想将其转换为类型为 Expression<Action<object, object>>
的 setter .如何实现?
问题是 object
范围。使用正确的类型 ( string
) 这会很容易。
class Foo
{
public Bar Bar { get; set; }
}
class Bar
{
public string Baz { get; set; }
}
static void Main(string[] args)
{
var expr = GetExpression(t => t.Bar.Baz);
var member = expr.Body as MemberExpression;
var p = Expression.Parameter(typeof(object), "p");
// This does not work...
var assign = Expression.Assign(member, p);
var lambda = Expression.Lambda<Action<object, object>>(assign, p);
object o = new Foo();
object v = "test";
lambda.Compile().Invoke(o, v);
}
private static Expression<Func<Foo, string>> GetExpression(Expression<Func<Foo, string>> expr)
{
return expr;
}
最佳答案
这是可能的,但并非微不足道。首先,您需要重写您的原始表达式。现在它有这种形式:
(Foo t) => t.Bar.Baz;
你需要它是这样的:
(object t) => ((Foo)t).Bar.Baz;
所以你需要表达式访问者:
private class ReplaceParameterExpressionVisitor : System.Linq.Expressions.ExpressionVisitor {
private readonly ParameterExpression _toReplace;
private readonly ParameterExpression _replaceWith;
public ReplaceParameterExpressionVisitor(ParameterExpression toReplace, ParameterExpression replaceWith) {
_toReplace = toReplace;
_replaceWith = replaceWith;
}
protected override Expression VisitParameter(ParameterExpression node) {
if (node == _toReplace)
// replace with new parameter and convert to the old parameter type
return Expression.Convert(_replaceWith, _toReplace.Type);
return base.VisitParameter(node);
}
}
然后你的代码变成:
static void Main(string[] args)
{
var expr = GetExpression(t => t.Bar.Baz);
var member = expr.Body as MemberExpression;
// define new parameter of type object
var target = Expression.Parameter(typeof(object), "t");
var value = Expression.Parameter(typeof(object), "p");
// replace old parameter of type Foo to new one
member = (MemberExpression) new ReplaceParameterExpressionVisitor(expr.Parameters[0], target).Visit(member);
// convert value to target type, because you cannot assign object to string
var assign = Expression.Assign(member, Expression.Convert(value, member.Type));
// now we have (target, value) => ((Foo)target).Bar.Baz = (string) value;
var lambda = Expression.Lambda<Action<object, object>>(assign, target, value);
var o = new Foo();
// set bar or will throw null reference
o.Bar = new Bar();
object v = "test";
lambda.Compile().Invoke(o, v);
}
关于c# - 从 Expression<Func<IMyclass, int>> 创建 setter Expression<Action<object, object>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43409713/
我有一个 Expression>我想将其转换为类型为 Expression> 的 setter .如何实现? 问题是 object范围。使用正确的类型 ( string) 这会很容易。 class F
我是一名优秀的程序员,十分优秀!