使用LINQ的动态表达式.如何找到厨房?

ser*_*hio 9 .net c# linq linq-expressions

我尝试实现用户动态过滤器,其中使用选择一些属性,选择一些运算符并选择值.

由于我没有找到这个问题的答案,我尝试使用LINQ表达式.
主要是我需要确定主要房间是厨房的所有房屋(任何感觉,我知道).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
//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 });

            //var kitchens = houses.AsQueryable<House>().Where("MainRoom.Type = RoomType.Kitchen");
            //Console.WriteLine("kitchens count = {0}", kitchens.Count());

            var houseParam = Expression.Parameter(typeof(House), "house");
            var houseMainRoomParam = Expression.Property(houseParam, "MainRoom");
            var houseMainRoomTypeParam = Expression.Property(houseMainRoomParam, "Type");

            var roomTypeParam = Expression.Parameter(typeof(RoomType), "roomType");

            var comparison = Expression.Lambda(
                Expression.Equal(houseMainRoomTypeParam,
                Expression.Constant("Kitchen", typeof(RoomType)))
                );

            // ???????????????????????? DOES NOT WORK
            var kitchens = houses.AsQueryable().Where(comparison);

            Console.WriteLine("kitchens count = {0}", kitchens.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
    }
}
Run Code Online (Sandbox Code Playgroud)

Vla*_*mir 6

var kitchens = from h in houses
               where h.MainRoom.Type == RoomType.Kitchen
               select h;
Run Code Online (Sandbox Code Playgroud)

但是你必须先RoomType在房间里设置房产.

好的,编辑:

所以你必须重新定义:

var comparison = Expression.Lambda<Func<House, bool>>(...
Run Code Online (Sandbox Code Playgroud)

然后,当你使用它时:

var kitchens = houses.AsQueryable().Where(comparison.Compile());
Run Code Online (Sandbox Code Playgroud)

编辑#2:

好的,你走了:

var roomTypeParam = Expression.Parameter(typeof(RoomType), "roomType");



// ???????????????????????? DOES NOT WORK
var comparison = Expression.Lambda<Func<House, bool>>(
    Expression.Equal(houseMainRoomTypeParam,
    Expression.Constant(Enum.Parse(typeof(RoomType), "Kitchen"), typeof(RoomType))), houseParam);



// ???????????????????????? DOES NOT WORK
var kitchens = houses.AsQueryable().Where(comparison);
Run Code Online (Sandbox Code Playgroud)

编辑#3:对于你的需求,我暂时没有想法.我给你最后一个:

在String类型上声明一个扩展方法:

internal static object Prepare(this string value, Type type)
{
    if (type.IsEnum)
        return Enum.Parse(type, value);

    return value;
}
Run Code Online (Sandbox Code Playgroud)

然后在表达式中使用它,如:

Expression.Constant("Kitchen".Prepare(typeof(RoomType)), typeof(RoomType))
Run Code Online (Sandbox Code Playgroud)

那是因为显然enum的处理方式不同.该扩展名将使其他类型的字符串保持不变.缺点:你必须在typeof()那里添加另一个.