C# 如何转换表达式<;Func<;T1,U>&燃气轮机;表达<;Func<;T2,U>>;?
考虑下面的示例项目。给定一个C# 如何转换表达式<;Func<;T1,U>&燃气轮机;表达<;Func<;T2,U>>;?,c#,linq-expressions,C#,Linq Expressions,考虑下面的示例项目。给定一个expression表达式,我想创建一个表达式,可以为实现根接口(IBase)的任何T调用该表达式 问题 下面的表达式转换器似乎可以工作,但在更高级的表达式中调用时,转换后的Func会抛出invalidoOperationException。到目前为止,我还无法复制这一点。尽管如此,通过查看结果表达式,我确实看到有两个参数-t和Param_0,我认为这两个参数会导致问题 System.InvalidOperationException:“IBase”类型的变量“t”
expression
表达式,我想创建一个表达式,可以为实现根接口(IBase
)的任何T
调用该表达式
问题
下面的表达式转换器似乎可以工作,但在更高级的表达式中调用时,转换后的Func
会抛出invalidoOperationException
。到目前为止,我还无法复制这一点。尽管如此,通过查看结果表达式,我确实看到有两个参数-t
和Param_0
,我认为这两个参数会导致问题
System.InvalidOperationException:“IBase”类型的变量“t”
从作用域“名称”引用,但未定义
必须以某种方式改进下面的转换方法。请告知
namespace ExpressionTest
{
interface IBase
{
string Name { get; set; }
}
interface IFoo : IBase
{
string Foo { get; set; }
}
interface IBar : IBase
{
string Bar { get; set; }
}
class FooImpl : IFoo
{
public FooImpl()
{
Name = "Name";
Foo = "Foo";
var e1 = Test<IBase, string>(t => t.Name);
var e2 = Test<IFoo, string>(t => t.Foo);
var e3 = Test<IBar, string>(t => t.Bar);
var e4 = Test2<IBase, string>((b, v) => Stuff(b, v));
e4.Compile().Invoke(this, "new");
var name = e1.Compile().Invoke(this);
var foo = e2.Compile().Invoke(this);
// TODO: Use "as" operator instead of cast...
// var bar = e3.Compile().Invoke(this);
}
public void Stuff(IBase b, string v)
{
b.Name = v;
}
public string Name { get; set; }
public string Foo { get; set; }
private Expression<Func<IBase, TProperty>>
Test<T, TProperty>(Expression<Func<T, TProperty>> expr)
where T : IBase
{
var p = Expression.Parameter(typeof(IBase));
var convert = Expression.Convert(p, typeof(T));
var invoke = Expression.Invoke(expr, convert);
var lambda = Expression.Lambda<Func<IBase, TProperty>>(invoke, p);
return lambda;
}
private Expression<Action<IBase, TProperty>>
Test2<T, TProperty>(Expression<Action<T, TProperty>> expr)
where T : IBase
{
var p1 = expr.Parameters.Last();
var p2 = Expression.Parameter(typeof(IBase));
var convert = Expression.Convert(p2, typeof(T));
var invoke = Expression.Invoke(expr, convert, p1);
var lambda = Expression.Lambda<Action<IBase, TProperty>>(invoke, p2, p1);
return lambda;
}
}
class Program
{
static void Main(string[] args)
{
var foo = new FooImpl();
}
}
}
如果不能复制您的错误,就很难说出哪里出了问题。使用LINQPad及其转储工具可以帮助查看表达式创建并比较它们 但是,将适当的条件逻辑添加到生成中并不困难 对于
测试
:
var iif = Expression.Condition(Expression.TypeIs(p, typeof(T)), invoke, Expression.Constant(null, typeof(TProperty)));
var lambda = Expression.Lambda<Func<IBase, TProperty>>(iif, p);
我发现了错误。在提取后来使用的内部调用时,我意外地使用了外部参数。谢谢你的
TypeIs
code。void
方法的第二个测试是吗?@l33t是,对于具有操作
参数的Test2
方法。
var iif = Expression.Condition(Expression.TypeIs(p, typeof(T)), invoke, Expression.Constant(null, typeof(TProperty)));
var lambda = Expression.Lambda<Func<IBase, TProperty>>(iif, p);
var iif = Expression.IfThen(Expression.TypeIs(p2, typeof(T)), invoke);
var lambda = Expression.Lambda<Action<IBase, TProperty>>(iif, p2, p1);