我尝试做实现用户动态过滤器,用在选择一些属性,选择一些运营商也选择了值。
由于我没有找到还没有一个答案这个问题,我试图使用LINQ EX pressions 。照片 主要是我需要找出所有的房屋其主要房间有厨房的(任何桑斯,我知道)。
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Linq.Ex pressions;
//使用System.Linq.Dynamic;
命名空间ConsoleApplication2
{
类节目
{
静态无效的主要(字串[] args)
{
房间aRoom =新房间(){名称=客房};
房间扫帚=新房间(){名称=B室};
客房克鲁姆=新房间(){名称=C室};
众议院的MyHouse =新房
{
客房=新的名单,其中,客房及GT;(新房间[] {} aRoom)
MainRoom = aRoom
};
众议院yourHouse =新楼()
{
客房=新的名单,其中,客房及GT;(新房间[] {扫帚,克鲁姆}),
MainRoom =扫帚
};
众议院donaldsHouse =新楼()
{
客房=新的名单,其中,客房及GT;(新房间[] {aRoom,扫帚,克鲁姆}),
MainRoom = aRoom
};
VAR房子=新的名单,其中,房屋及GT;(新房[] {的MyHouse,yourHouse,donaldsHouse});
// VAR厨房= houses.AsQueryable<家>(),其中(MainRoom.Type = RoomType.Kitchen)。
//Console.WriteLine("kitchens数= {0},kitchens.Count());
VAR houseParam =前pression.Parameter(typeof运算(楼),房子);
VAR houseMainRoomParam =前pression.Property(houseParam,MainRoom);
VAR houseMainRoomTypeParam =前pression.Property(houseMainRoomParam,类型);
VAR roomTypeParam =前pression.Parameter(typeof运算(RoomType),roomType);
VAR比较=前pression.Lambda(
防爆pression.Equal(houseMainRoomTypeParam,
防爆pression.Constant(厨房的typeof(RoomType)))
);
// ????????????????????????不工作
VAR厨房= houses.AsQueryable(),其中(比较)。
Console.WriteLine(厨房数= {0},kitchens.Count());
Console.ReadKey();
}
}
公共类之家
{
公共字符串的地址{获得;组; }
公共双区{获得;组; }
公共房间MainRoom {获得;组; }
公开名单<房间>客房{获得;组; }
}
公共类房
{
公共双区{获得;组; }
公共字符串名称{;组; }
公共RoomType类型{获取;组; }
}
公共枚举RoomType
{
厨房,
卧室,
图书馆,
办公室
}
}
解决方案
VAR的厨房,距离H =的房屋
其中,h.MainRoom.Type == RoomType.Kitchen
选择H;
但你必须设置在房间之前, RoomType
属性。
好吧,编辑:
所以你必须重新定义:
VAR比较=前pression.Lambda< Func键<府,布尔>>(...
然后,当你使用它:
VAR厨房= houses.AsQueryable(),其中(comparison.Compile())。
编辑#2:
好了,在这里你去:
VAR roomTypeParam =前pression.Parameter(typeof运算(RoomType),roomType);
// ????????????????????????不工作
VAR比较=前pression.Lambda< Func键<府,布尔>>(
防爆pression.Equal(houseMainRoomTypeParam,
防爆pression.Constant(Enum.Parse(typeof运算(RoomType),厨房)的typeof(RoomType))),houseParam);
// ????????????????????????不工作
VAR厨房= houses.AsQueryable(),其中(比较)。
编辑#3:为您的需求,我的想法现在。我举一个最后一个你:
在String类型声明扩展方法:
内部静态对象prepare(此字符串值,类型类型)
{
如果(type.IsEnum)
返回Enum.Parse(类型,值);
返回值;
}
然后用它在EX pression这样的:
防爆pression.Constant(厨房。prepare(typeof运算(RoomType))的typeof(RoomType))
这是因为显然枚举的处理方式不同。该分机将离开该字符串不变为其他类型。缺点:您需要添加另一个 typeof运算()
有
I try do implement a user dynamic filter, where used selects some properties, selects some operators and selects also the values.
As I didn't find yet an answer to this question, I tried to use LINQ expressions. Mainly I need to identify all houses which main rooms are kitchens(any sens, I know).
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
}
}
解决方案
var kitchens = from h in houses
where h.MainRoom.Type == RoomType.Kitchen
select h;
But you must set the RoomType
property on the rooms before.
Ok, edit:
so you must redefine:
var comparison = Expression.Lambda<Func<House, bool>>(...
Then, when you use it:
var kitchens = houses.AsQueryable().Where(comparison.Compile());
Edit #2:
Ok, here you go:
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);
Edit #3: Of, for your needs, I am out of ideas for now. I give you one last one:
Declare an extension method on the String type:
internal static object Prepare(this string value, Type type)
{
if (type.IsEnum)
return Enum.Parse(type, value);
return value;
}
Then use it in that expression like:
Expression.Constant("Kitchen".Prepare(typeof(RoomType)), typeof(RoomType))
That's because apparently enums are treated differently. That extension will leave the string unaltered for other types. Drawback: you have to add another typeof()
there.