Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用contains方法为列表为int的枚举属性生成LINQ Lambda表达式_C#_Linq_Lambda_Enums_Expression - Fatal编程技术网

C# 使用contains方法为列表为int的枚举属性生成LINQ Lambda表达式

C# 使用contains方法为列表为int的枚举属性生成LINQ Lambda表达式,c#,linq,lambda,enums,expression,C#,Linq,Lambda,Enums,Expression,我已经建立了一些扩展方法,用于使用IQueryable对泛型对象进行排序和过滤,以从中获取数据,到目前为止,它对所有类型都很有效,但对于枚举,我不知道如何解决这个问题,所以这里有一些示例 public enum ClaimStatusEnum { None = 0, Open = 10, Submitted = 20, Rejected = 30, Refunded = 40, Closed = 50, Received = 60,

我已经建立了一些扩展方法,用于使用IQueryable对泛型对象进行排序和过滤,以从中获取数据,到目前为止,它对所有类型都很有效,但对于枚举,我不知道如何解决这个问题,所以这里有一些示例

    public enum ClaimStatusEnum
{
    None = 0,
    Open = 10,
    Submitted = 20,
    Rejected = 30,
    Refunded = 40,
    Closed = 50,
    Received = 60,
    Backorder = 70,
    UnderReview = 80
}
请注意!这只是一个枚举的示例,但我不知道在执行时枚举类型是什么,所以请注意,我必须使用泛型类型

下面是一个示例,其中包含一个包含该枚举类型的属性

 public class Claim
{
    [Key]
    public int Id { get; set; }
    public DateTime DateCreated { get; set; }      
    public ClaimStatusEnum ClaimStatus { get; set; }

}
下面是一个过滤器的示例,该过滤器通过枚举中的int值列表传递

var arr = new int[] { 20, 30, 40 };
现在,本例中的goel是在Claim表中找到的,在该表中,我们有带有枚举值的记录,这些记录在int的arr中

所以我想构建一个lambda表达式,它应该是泛型的,而不是硬编码类的类型,因为它可以是任何实体,也应该适用于任何给定的枚举

这是我目前使用的完全相同的东西,但唯一的区别是它适用于int而不是enum的属性,所以它对int类型非常有效,但是当涉及到enum类型时,我得到了一个错误

                    ConstantExpression c = Expression.Constant(arr);
                MethodInfo mi = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                               .Where(m => m.Name == "Contains")
                               .Single(m => m.GetParameters().Length == 2)
                               .MakeGenericMethod(typeof(int));
                call = Expression.Call(mi, c, m);
这里有人能帮我如何使枚举类型工作吗?我已经尝试了很多不同的方法,它们都会出错

                    ConstantExpression c = Expression.Constant(arr);
                MethodInfo mi = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                               .Where(m => m.Name == "Contains")
                               .Single(m => m.GetParameters().Length == 2)
                               .MakeGenericMethod(typeof(int));
                call = Expression.Call(mi, c, m);
下面是如何将其用作扩展方法

        public static IQueryable<T> EntitySortAndFilter<T>(this IQueryable<T> data, PageFilter filter, T type)
    {

        foreach (var item in filter.Filter.Filters)
        {
            if (item.Value == null || item.Condition == null || item.Field == null)
                continue;

            ParameterExpression e;
            Expression m, call;
            PropertyInfo prop;

            prop = type.GetType().GetProperty(item.Field, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
            e = Expression.Parameter(type.GetType(), "e");
            m = Expression.MakeMemberAccess(e, prop );

            
            var arr = item.Value;
                ConstantExpression c = Expression.Constant(arr);
                MethodInfo mi = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                               .Where(m => m.Name == "Contains")
                               .Single(m => m.GetParameters().Length == 2)
                               .MakeGenericMethod(typeof(int));
                call = Expression.Call(mi, c, m);

            var lambda = Expression.Lambda<Func<T, bool>>(call, e);
            data = data.Where(lambda);

           


        } 

       return data;  

    }

但是,它应该适用于我想要的任何实体,这就是为什么它是通用的。

我认为您需要这样做:

if(prop.PropertyType.IsEnum) // if property is enum
{    
    // create expression to cast array values to enum
    var castMi = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(prop.PropertyType);
    var castArrToEnum = Expression.Call(castMi, Expression.Constant(arr)));
    // make contains for needed type
    mi = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
            .Where(m => m.Name == "Contains")
            .Single(m => m.GetParameters().Length == 2)
            .MakeGenericMethod(prop.PropertyType);
    call = Expression.Call(mi, castArrToEnum, m);
}
如果这不起作用,您可以尝试换一种方式:

var mc = Expression.Convert(m, typeof(int)); 
ConstantExpression c = Expression.Constant(arr); 
MethodInfo mi = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public) 
    .Where(m => m.Name == "Contains") 
    .Single(m => m.GetParameters().Length == 2) 
    .MakeGenericMethod(typeof(int)); 
call = Expression.Call(mi, c, mc);

1) 你犯了什么错误?2)
.MakeGenericMethod(typeof(int))
->
.MakeGenericMethod(typeof(ClaimStatusEnum))
?我不能做typeof(ClaimStatusEnum),因为它可以是任何给定的枚举,它必须是generic。您能添加预期的用法吗?此外,您还可以始终为枚举类型添加泛型类型参数。我使用example.System.invalidoOperationException更新了该问题:“NavigationExpandingExpressionVisitor”对LINQ表达式“AsQueryable((IEnumerable)int[]{0,20,})”的处理失败。这可能表明EF核心中存在缺陷或限制。有关更多详细信息,请参阅。在Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCallExpression(MethodCallExpression MethodCallExpression)中,代码片段也有一些拼写错误,下面是我使用的。call=Expression.call(mi,castarrteonum,m);另外还有一个额外的)at Expression.Constant(arr)@SolStein更改了
调用=
部分。您的异常非常奇怪,因为我没有将
arr
转换为
IEnumerable
,我的代码应该生成
arr.cast()
我想这行正在执行var castMi=typeof(Enumerable).GetMethod(“cast”)@SolStein还可以尝试另一种方法—将属性强制转换为
int
-
表达式。转换(m,typeof(int))
并将其传递给
调用,而不是
m