我有两个类型为 : 的表达式树,Expression<Func<string, bool>>我想获得一个表达式来执行两个表达式的 OR(将相同的字符串参数传递给两个表达式)知道吗?
给定一个具有字典属性的类
public class Product
{
public Dictionary<string, string> Attributes { get { return attributes; } }
private Dictionary<string, string> attributes = new Dictionary<string, string>();
}
Run Code Online (Sandbox Code Playgroud)
我希望能够根据从数据存储中检索到的条件来匹配产品列表中的产品
Brand == Tyco
Color != Blue
Run Code Online (Sandbox Code Playgroud)
我目前的方法是从过滤器构造一个表达式,然后将该表达式作为参数传递给 LINQWhere方法调用,如下所示
products = products.Where(myConstructedExpression);
Run Code Online (Sandbox Code Playgroud)
哪里myConstructedExpression通常是一个 lamda 表达式,看起来像
p => p.Attributes[attribute] == value
Run Code Online (Sandbox Code Playgroud)
我已经组装了以下代码用于测试目的,但lambda.Compile()无论我为他留下的表达式尝试了什么,它总是无法调用。
Dictionary<string, ExpressionType> expressionType = new Dictionary<string, ExpressionType>();
expressionType.Add("==", ExpressionType.Equal);
expressionType.Add("!=", ExpressionType.NotEqual);
string filter = "Brand == Tyco";
string[] fields = filter.Split(' ');
string attribute = fields[0];
string op …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用表达式树来构建一对嵌套的组,并且完全被 Select 及其对参数的期望所困扰。我最终想要做的是通过表达式树来构建它;
var queryNestedGroups = products.GroupBy(x => x.Category)
.Select(p => new
{
key = p.Key,
objects = p.ToList().GroupBy(y => y.Subcategory)
.Select(y => new { key = y.Key, objects = y.ToList() })
})
.AsQueryable();
Run Code Online (Sandbox Code Playgroud)
这是我迄今为止的尝试(产品是一个列表);
var data = Expression.Constant(products);
var arg = Expression.Parameter(typeof(Product), "arg");
var nameProperty = Expression.PropertyOrField(arg, "Category");
var groupByLambda = Expression.Lambda<Func<Product, string>>(nameProperty, arg);
var groupByExpression = Expression.Call(
typeof(Queryable),
"GroupBy",
new Type[] { typeof(Product), typeof(string) },
data,
groupByLambda);
var parameterExp = Expression.Parameter(typeof(IGrouping<string, Product>), "p");
var keyProp = Expression.PropertyOrField(parameterExp, "Key"); …Run Code Online (Sandbox Code Playgroud) 我不知道为什么我要阅读表达式树,但我是。因此,我不了解该对象,也不了解它的使用地点或方式。
在这里阅读其他问题,例如什么是表达式树以及如何使用它们以及为什么要使用它们?(以及他们引用的链接),我现在对表达式树有了更好的理解,但是,我仍然不知道为什么使用它。
关于原因,我见过的唯一示例是 Linq to SQL 之类的东西 - 但是当您对其进行更多调查时,它似乎实际上更多地是关于它与IQueryable<T>界面的使用。
表达式树是否仅与IQueryable 接口结合使用(使用)?
我是表达式树的新手,我需要将下面的 lambda 转换为表达式树
Data.Where(s => s.Property.ToString().StartsWith("My Search Data"));
Run Code Online (Sandbox Code Playgroud)
但是我已经完成了
Data.Where(s => s.Property.StartsWith("My Search Data");
Run Code Online (Sandbox Code Playgroud)
现在我需要在使用 StartsWith 之前使用 ToString 方法。
下面是我的示例代码。
ParameterExpression e = Expression.Parameter(typeof(T), "e");
PropertyInfo propertyInfo = typeof(T).GetProperty(field);
MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
ConstantExpression c = Expression.Constant(data, typeof(string));
MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
Expression call = Expression.Call(m, mi, c);
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, e);
query = query.Where(lambda);
Run Code Online (Sandbox Code Playgroud) List<>我有一个反射代码,用于创建(运行时已知的类型参数)的实例,并调用Add方法向其添加一些值。我的片段是这样的:
// here is my type parameter
var genericType = typeof(MyRunTimeType);
// here is a list of my values
MyRunTimeType[] values = MyRunTimeValuesOfTypeMyRunTimeType();
// creating instance of List<>
var listType = typeof(List<>);
var listGenericType = listType.MakeGenericType(genericType);
var listInstance = Activator.CreateInstance(listGenericType);
// getting Add method and call it
var addMethod = listGenericType.GetMethod("Add", genericType);
foreach (var value invalues)
addMethod.Invoke(listInstance, new[] { value });
Run Code Online (Sandbox Code Playgroud)
那么,您建议如何将此反射片段转换为表达式树?
更新:
好吧,我写了这个片段,它似乎无法工作:
public static Func<IEnumerable<object>, object> GetAndFillListMethod(Type genericType) {
var listType = typeof(List<>);
var listGenericType …Run Code Online (Sandbox Code Playgroud) 我正在尝试从名为 的 IQueryable 上的一串属性名称(由用户给出)构建动态表达式source。这是我到目前为止所拥有的:
var parameter = Expression.Parameter(source.ElementType, "x");
var member = propertyChain.Split('.').Aggregate((Expression)parameter, Expression.PropertyOrField);
var selector = Expression.Lambda(member, parameter);
Run Code Online (Sandbox Code Playgroud)
这会给我一些类似x => x.MainProperty.SubProperty输入时的信息MainProperty.SubProperty。
我现在需要添加ToString()到表达式中selector,以便它将生成表达式x => x.MainProperty.SubProperty.ToString(),然后可以将其传递到其他方法中。
如何才能做到这一点?
我正在尝试建立一种动态GroupBy,其中密钥的类型并不重要。但分组依据的属性可以是类型Guid或int其他类型。这就是为什么我需要打电话ToString()。
public static IEnumerable<IGrouping<string, T>>(IQueryable<T> source, string propertyChain)
{
var parameter = Expression.Parameter(source.ElementType, "x");
var member = propertyChain.Split('.').Aggregate((Expression)parameter, Expression.PropertyOrField);
var selector = Expression.Lambda(member, parameter);
// currently here I have x => x.MainProperty.SubProperty
// …Run Code Online (Sandbox Code Playgroud) 我怀着极大的热情在 EF Core 7 中发现了 ExecuteDeleteAsync 和 ExecuteUpdateAsync。它们有助于使我的代码变得更简单、更快。无需使用自制程序批量删除或更新1-2个字段。无论如何,我遇到过应该在运行时选择要更新的数据库的确切表和字段的情况。
我可以使用数据库表:
public static IQueryable<object> Set(this DbContext context, Type entity) =>
context.ClrQuery(context.ClrType(entity));
Run Code Online (Sandbox Code Playgroud)
我有制作表达式来过滤行的方法:
public static IQueryable Where(this IQueryable source, string equalProperty, object value, [NotNull] Type EntityType)
{
PropertyInfo? property = EntityType.GetProperty(equalProperty);
if (property == null)
throw new NotImplementedException($"Type {EntityType.Name} does not contain property {equalProperty}");
ParameterExpression parameter = Expression.Parameter(EntityType, "r");
MemberExpression member = Expression.MakeMemberAccess(parameter, property);
LambdaExpression whereExpression = Expression.Lambda(Expression.Equal(member, Expression.Constant(value, property.PropertyType)), parameter);
MethodCallExpression resultExpression = WhereCall(source, whereExpression);
return source.Provider.CreateQuery(resultExpression);
}
Run Code Online (Sandbox Code Playgroud)
所以我可以找到要更新的行
IQueryable Source = …Run Code Online (Sandbox Code Playgroud) linq expression-trees entity-framework-core c#-11.0 ef-core-7.0
我使用这段代码,但出现错误:
错误:System.ArgumentException:“...GreenPaperItem”类型的表达式不能用于方法“Boolean”的“System.Runtime.CompilerServices.Closure”类型的参数
public static Expression<Func<T, bool>> ToExpression<T>(Func<T, bool> p)
{
ParameterExpression p0 = Expression.Parameter(typeof(T));
ParameterExpression p1 = Expression.Parameter(typeof(bool));
return Expression.Lambda<Func<T, bool>>(Expression.Call(p.Method, p0, p1),
new ParameterExpression[] { p0, p1 });
}
Run Code Online (Sandbox Code Playgroud)
该表达式旨在用于 linq toEntity IQueriyable 查询:
query = query.Where(ToExpression<GreenPaperItem>(filter.GenerateFilterFunction()));
Run Code Online (Sandbox Code Playgroud) 试着习惯F#我尝试了一些小例子,我的下一步是为逻辑计算/评估编写一些函数,现在我有了这个结构
type Expr =
| True
| False
| Not of Expr
| And of Expr * Expr
Run Code Online (Sandbox Code Playgroud)
它应该是显而易见的我想达到的目标:能够封装喜欢不同的功能Not,并And像一个计算中使用And(And(True, Not(False)), True),但目前我不明白(这是我第一次wrinting这种"复杂"的功能代码)如何使用这个结构并编写正确的方法,例如我可以编写用于评估
let evalLogic (expr : Expr) : bool =
match expr with
| True -> true
| False -> false
| _ -> false (* eval the expression which is not "atomic" *)
Run Code Online (Sandbox Code Playgroud)
然后作为一种方法
let And (left : Expr , right : Expr ) : Expr =
let value = evalLogic(left) && evalLogic(right)
match …Run Code Online (Sandbox Code Playgroud) expression-trees ×10
c# ×7
expression ×4
lambda ×3
linq ×3
.net ×2
reflection ×2
c#-11.0 ×1
ef-core-7.0 ×1
f# ×1
logic ×1