Dynamic Expression using LINQ. How To Find the Kitchens?

荒凉一梦 提交于 2019-11-30 18:44:40
Vladimir
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.

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

The Where method takes a Func<House, bool> or a Expression<Func<House, bool>> as the parameter, but the variable comparison is of type LambdaExpression, which doesn't match. You need to use another overload of the method:

var comparison = Expression.Lambda<Func<House, bool>>(
                Expression.Equal(houseMainRoomTypeParam,
                Expression.Constant("Kitchen", typeof(RoomType))));
//now the type of comparison is Expression<Func<House, bool>>

//the overload in Expression.cs
public static Expression<TDelegate> Lambda<TDelegate>(Expression body, params ParameterExpression[] parameters);

I wouldn't build the where clause in that way - I think it's more complex than it needs to be for your needs. Instead, you can combine where clauses like this:

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

// A basic predicate which always returns true:
Func<House, bool> 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<House>().Where(housePredicate);

I tested this one, honest :)

what about this

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);
Amine

To add a new Enum type to dynamic Linq, you must add the following code :

typeof(Enum),
typeof(T)

T : Enum type

in predefined types of dynamic. That works for me.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!