gpt4 book ai didi

c# - 如何使用类型变量的类型参数创建表达式>

转载 作者:太空狗 更新时间:2023-10-29 19:59:38 25 4
gpt4 key购买 nike

我想写一个像下面这样的语句:

Expression<Func<AClass, bool>> filter = x => true;

除了 AClass 之外,我想使用在运行时确定的 Type 变量。所以,概念上是这样的:

Type aClassType = methodParameter.GetType();
Expression<Func<aClassType, bool>> filter = x => true;

显然语法会有很大的不同。我假设我需要使用某种反射或其他幻想。

最终目标

这里的最终目标有点复杂,因此我对上面的示例进行了极大的简化。将要使用此委托(delegate)的实际 .Where 调用看起来更像这样:

var copy = iQ;

...

copy = copy.Where( p1 => iQ.Where( p2 => pgr2.Key == p1.Key && p2.DataField == column.DataField && p2.ColumnText.Contains( requestValue ) ).Any() );

p1 和 p2 的所有属性都是 IQueryable iQ 元素类型的父类的属性。我要创建的 Type 变量将是 iQ 的实际元素类型,即子类。

我该怎么做?

目前的进展

根据以下答案,我编写了这段测试代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace IQueryableWhereTypeChange {
class Program {
static void Main( string[] args ) {
var ints = new List<ChildQueryElement>();

for( int i = 0; i < 10; i++ ) {
ints.Add( new ChildQueryElement() { Num = i, Value = i.ToString() } );
}

IQueryable<ChildQueryElement> theIQ = ints.AsQueryable();

Type type = typeof(ChildQueryElement);
var body = Expression.Constant(true);
var parameter = Expression.Parameter(type);
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(Boolean));
var lambda = Expression.Lambda( delegateType, body, parameter );

Console.WriteLine( lambda.GetType() );

dynamic copy = theIQ;

Type copyType1 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType1 = ((IQueryable)copy).ElementType;
Console.WriteLine( "copyType1 : " + copyType1.ToString() );
Console.WriteLine( "elementType1 : " + elementType1.ToString() );

copy = Queryable.Where( copy, lambda );

Type copyType2 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType2 = ((IQueryable)copy).ElementType;
Console.WriteLine( "copyType2 : " + copyType2.ToString() );
Console.WriteLine( "elementType2 : " + elementType2.ToString() );
}
}

public class ParentQueryElement {
public int Num { get; set; }
}
public class ChildQueryElement : ParentQueryElement {
public string Value { get; set; }
}
}

那个程序有这样的输出:

System.Linq.Expressions.Expression`1[System.Func`2[IQueryableWhereTypeChange.ChildQueryElement,System.Boolean]]  
copyType1 : IQueryableWhereTypeChange.ChildQueryElement
elementType1 : IQueryableWhereTypeChange.ChildQueryElement

Unhandled Exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
The best overloaded method match for
'System.Linq.Queryable.Where<IQueryableWhereTypeChange.ChildQueryElement>(
System.Linq.IQueryable<IQueryableWhereTypeChange.ChildQueryElement>,
System.Linq.Expressions.Expression<System.Func<IQueryableWhereTypeChange.ChildQueryElement,bool>>
)'
has some invalid arguments
at CallSite.Target(Closure , CallSite , Type , Object , LambdaExpression )
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at IQueryableWhereTypeChange.Program.Main(String[] args)

在我尝试复制我的复杂谓词之前,我希望它能正常工作。

我发现异常令人费解,因为 lambda.GetType() 的输出几乎与异常中的类型完全匹配。唯一的区别是 System.Booleanbool,但这无关紧要。

最佳答案

您需要创建适当的委托(delegate)类型,然后将其传递给 Expression.Lambda方法。例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

class Test
{
static void Main()
{
var type = typeof(string);
var body = Expression.Constant(true);
var parameter = Expression.Parameter(type);
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool));
dynamic lambda = Expression.Lambda(delegateType, body, parameter);
Console.WriteLine(lambda.GetType()); // Expression<string, bool>
}
}

现在当然是你的 body通常不会只是一个常数 - 但我们不知道你需要在那里做什么。从你编辑的问题来看,你似乎确实有一些类型的静态类型知识,否则你将无法表达那个 lambda 表达式。因此,您要么需要手动构建表达式树以等效于 lambda 表达式(使用 Expression.Property 等),要么根据您所知道的创建一个表达式树,然后使用表达式树访问者使其适应实际类型.

编辑:注意 lambda 的类型必须是 dynamic让它作为 Queryable.Where 的第二个参数,否则 C# 编译器的执行时版本将使用变量的静态类型(即 LambdaExpression )来约束重载解析。您希望它匹配实际的 Expression<TDelegate>类型,你不能在编译时表达,所以你需要使用 dynamic .

关于c# - 如何使用类型变量的类型参数创建表达式<Func<>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25793736/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com