如何在动态Linq中使用枚举?

9

我想在我的动态LINQ查询中使用枚举类型。

这个是否可行,如果可以,怎么做呢?

请看下面的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Room aRoom = new Room() { Name = "a Room" };
            Room bRoom = new Room() { Name = "b Room" };
            Room cRoom = new Room() { Name = "c Room" };

            House myHouse = new House
            {
                Rooms = new List<Room>(new Room[] { aRoom }),
                MainRoom = aRoom
            };
            House yourHouse = new House()
            {
                Rooms = new List<Room>(new Room[] { bRoom, cRoom }),
                MainRoom = bRoom
            };
            House donaldsHouse = new House()
            {
                Rooms = new List<Room>(new Room[] { aRoom, bRoom, cRoom }),
                MainRoom = aRoom
            };

            var houses = new List<House>(new House[] { myHouse, yourHouse, donaldsHouse });

            // MainRoom.Name = \"a Room\" and Rooms.Count = 3 or 
            // ?????????????????????????
            var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = \"RoomType.Kitchen\"");

            Console.WriteLine("aRoomsHouses count = {0}", aRoomsHouses.Count());
            Console.ReadKey();
        }
    }

    public class House
    {
        public string Address { get; set; }
        public double Area { get; set; }
        public Room MainRoom { get; set; }
        public List<Room> Rooms { get; set; }
    }

    public class Room
    {
        public double Area { get; set; }
        public string Name { get; set; }
        public RoomType Type { get; set; }
    }

    public enum RoomType
    {
        Kitchen,
        Bedroom,
        Library,
        Office
    }
}

你需要使用动态LINQ吗?这可以通过标准LINQ完成。 - Dean Chalk
1
@Dean: 我需要动态 LINQ。 - serhio
5个回答

21

我遇到了同样的问题,试过了@Steve Wilkes标记的答案,但对我没有用! 然后我发现动态LINQ在同一包中有一个HTML文档,其中提到可以将枚举指定为字符串字面值。

houses.AsQueryable<House>().Where("MainRoom.Type = \"Kitchen\"")

这对我有用。


3
谢谢!以上方法都没有奏效,但是使用枚举值名称作为文字量非常有效。 - Ales Potocnik Hahonina

4

这个可以工作:

houses.AsQueryable<House>()
    .Where("MainRoom.Type = ConsoleApplication2.RoomType.Kitchen")

第一个不起作用。找不到“int”作为“House”属性...第二个也不起作用,原因相同...总的来说,你不能使用“==”,而是要使用“=”。恐怕你没有测试过你的查询... - serhio
抱歉 - 你说得很对 - 我从模糊的记忆中写了两个选项...我刚刚测试了两个选项,第一个不行,但是第二个只有一个等号符号可以正常工作,所以我更新了我的答案,只包括那个。 - Steve Wilkes
你说得对。你的查询有效,所以这可能是一个好答案。不过,我已经在其他地方发布了:),所以也想知道如何使它工作https://dev59.com/ZFrUa4cB1Zd3GeqPik8g - serhio
我也回答了那个问题 :) - Steve Wilkes
你能否尝试修改这个枚举并查看上述表达式是否给出正确的结果?新枚举: public enum RoomType { 卧室, 厨房, // 将厨房移动到第二个位置 图书馆, 办公室 } - hungryMind
是的,改变顺序似乎没有任何区别。显然这不符合重构友好性,但我不认为@serhio会像这样直接将枚举值编写为字符串 - 答案的主要重点是只要枚举引用是完全限定的,它就能正常工作。 - Steve Wilkes

1
另外,还有另一种变体使用参数。
var aRoomsHouses = houses.AsQueryable<House>().Where("MainRoom.Type = @0",RoomType.Kitchen);

0

这应该可以工作

houses.AsQueryable<House>().Where(rs=>rs.MainRoom.Type == RoomType.Kitchen);

为什么在这种情况下需要动态LINQ?你期望的输出是什么?
我个人偏好避免使用容易出错的字符串。如果您的类或属性名称更改了,您将无法找到错误,直到遇到它。
最好使用表达式。
    Expression<Func<House, bool>> 
        filter = (p) => p.MainRoom.Type == RoomType.Kitchen; 
        filter = (p) => p.MainRoom.Area > 200;
        filter = (p) => p.Rooms.Sum(rs => rs.Area) > 500;
        filter = (p) => p.Address.Contains("abc");
        filter = (p) => p.Area > 200;
        ...
    var aRoomsHouses = houses.AsQueryable<House>().Where(filter);

您可以创建表达式,决定使用哪个字符串过滤器。最好创建一个静态类或者 switch 语句,它会给您不同类型的表达式,您可以将其用作 where 参数。


静态链接不行...我需要动态的Linq,因为我根据用户的过滤规范动态构建过滤器。 - serhio
你卡在了“动态”的词上。你可以使用标准的linq进行这种类型的查询。 - Andrew Barber
@serhio,你可以将操作传递到where方法中,你可以编写自己的方法来构建表达式,这些表达式可以在filter方法中使用。 - hungryMind
@serhio,我理解用户将从下拉菜单中选择房间类型和厨房,或者选择区域并输入> 200之类的内容。根据用户的输入,您将构建字符串表达式(我不认为您会要求用户输入“MainRoom.Type = ConsoleApplication2.RoomType.Kitchen”)。在构建过滤器字符串的点上,您也可以构建表达式。 - hungryMind
1
@Andrew Barber:使用谓词构建器,您始终可以为每个情况部分设置开关,换句话说,您硬编码了每个属性,这使得添加新属性变得不可能而不更改开关代码。 - serhio
显示剩余7条评论

-1

为了向动态 LINQ 添加一个新的枚举类型,您必须添加以下代码:

typeof(Enum),
typeof(T)

T : Enum type

在动态预定义类型中, 这对我很有用;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接