使用LINQ进行动态表达。 如何找到厨房?
我尝试实现用户动态filter,其中使用选择一些属性,选择一些运算符并选择值。
由于我没有找到这个问题的答案,我尝试使用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(new Room[] { aRoom }), MainRoom = aRoom }; House yourHouse = new House() { Rooms = new List(new Room[] { bRoom, cRoom }), MainRoom = bRoom }; House donaldsHouse = new House() { Rooms = new List(new Room[] { aRoom, bRoom, cRoom }), MainRoom = aRoom }; var houses = new List(new House[] { myHouse, yourHouse, donaldsHouse }); //var kitchens = houses.AsQueryable().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 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 } }
var kitchens = from h in houses where h.MainRoom.Type == RoomType.Kitchen select h;
但您必须先在房间中设置RoomType
属性。
好的,编辑:
所以你必须重新定义:
var comparison = Expression.Lambda>(...
然后,当你使用它时:
var kitchens = houses.AsQueryable().Where(comparison.Compile());
编辑#2:
好的,你走了:
var roomTypeParam = Expression.Parameter(typeof(RoomType), "roomType"); // ???????????????????????? DOES NOT WORK var comparison = Expression.Lambda>( Expression.Equal(houseMainRoomTypeParam, Expression.Constant(Enum.Parse(typeof(RoomType), "Kitchen"), typeof(RoomType))), houseParam); // ???????????????????????? DOES NOT WORK var kitchens = houses.AsQueryable().Where(comparison);
编辑#3:对于你的需求,我暂时没有想法。 我给你最后一个:
在String类型上声明一个扩展方法:
internal static object Prepare(this string value, Type type) { if (type.IsEnum) return Enum.Parse(type, value); return value; }
然后在表达式中使用它,如:
Expression.Constant("Kitchen".Prepare(typeof(RoomType)), typeof(RoomType))
这是因为显然enum的处理方式不同。 该扩展名将使字符串保持不变为其他类型。 缺点:你必须在那里添加另一个typeof()
。
// ???????????????????????? DOES NOT WORK var kitchens = houses.AsQueryable().Where(comparison);
Where
方法采用Func
或Expression
作为参数,但变量comparison
的类型为LambdaExpression
,不匹配。 您需要使用该方法的另一个重载:
var comparison = Expression.Lambda>( Expression.Equal(houseMainRoomTypeParam, Expression.Constant("Kitchen", typeof(RoomType)))); //now the type of comparison is Expression> //the overload in Expression.cs public static Expression Lambda (Expression body, params ParameterExpression[] parameters);
我不会以这种方式构建where子句 – 我认为它比你需要的更复杂。 相反,你可以结合这样的where子句:
var houses = new List(new House[] { myHouse, yourHouse, donaldsHouse }); // A basic predicate which always returns true: Func housePredicate = h => 1 == 1; // A room name which you got from user input: string userEnteredName = "a Room"; // Add the room name predicate if appropriate: if (!string.IsNullOrWhiteSpace(userEnteredName)) { housePredicate += h => h.MainRoom.Name == userEnteredName; } // A room type which you got from user input: RoomType? userSelectedRoomType = RoomType.Kitchen; // Add the room type predicate if appropriate: if (userSelectedRoomType.HasValue) { housePredicate += h => h.MainRoom.Type == userSelectedRoomType.Value; } // MainRoom.Name = "a Room" and Rooms.Count = 3 or // ????????????????????????? var aRoomsHouses = houses.AsQueryable ().Where(housePredicate);
我测试过这个,诚实:)
那这个呢
var kitchens = houses .SelectMany(h => h.Rooms, (h, r) => new {House = h, Room = r}) .Where(hr => hr.Room.Type == RoomType.Kitchen) .Select(hr => hr.House);
要向动态Linq添加新的Enum
类型,您必须添加以下代码:
typeof(Enum), typeof(T) T : Enum type
在预定义的动态类型中。 这对我行得通。
上述就是C#学习教程:使用LINQ进行动态表达。 如何找到厨房?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1039007.html