-2

In Winform application using EntityFramework, I implement a generic Search / Filter UI Components using BindingSource of the BaseForm and build search/filter string expression dynamically from user inputs and properties of the DataSource of BindingSource (Context entity).

Find and Filter aren't supported by the BindingSource in EntityFramework, because the query result of ObjectContext or DataContext was IEnumerable type, which didn't implement IBindingList interface ref

As a workaround I Cast BindingSource to List<T>.

To implement one, I use List<T>.Find(predicate) and the predicate is a lambda Expression.

To Pass a Predicate to List<T>.Find(predicate), I need To convert the dynamic generated string expression to Predicate .

String Expression example:

"CategoryId = 5 and Price < 10"

To Something using a method like:

Predicate<T>  GetPredicate <T>(string expression)
{   
    //how  to convert the string expressions to    Predicate<T> 
}

Then pass the predicate to the method List<T>. Find(predicat)

I can use .Where (dynamicStringExpression), but for my component I need GetPredicate(dynamicStringExpression)

How to get Predicate<T> from string expressions

M.Hassan
  • 10,282
  • 5
  • 65
  • 84
  • 3
    You better use Dynamic LINQ. – Gert Arnold Feb 19 '18 at 14:44
  • I used Dynamic LINQ in Where, but i can't use it as a predicate in `List.Find(predicate)`, can you show me an example. – M.Hassan Feb 19 '18 at 14:54
  • But I presume you get the Customers from a database. You better filter them before creating a list. Why do you want to filter them again? This starts looking like an [XY problem](https://meta.stackexchange.com/q/66377/168269). – Gert Arnold Feb 19 '18 at 17:10
  • In Winform application using EF, I try to build a generic Find , Filter UI using bindingsource. Find isn't supported by bindingsource in EF, and i try to implement one, and List..Find(predicate)` is a workaround :) . – M.Hassan Feb 19 '18 at 18:24
  • @Gert Arnold, I updated the question based on your comments. I think,as you said,Dynamic LINQ is promising. I start to review the source code. – M.Hassan Feb 20 '18 at 09:51
  • @M.Hassan this sounds like an XY Problem, Predicates aren't going to be equivalent unless they are the same reference, otherwise you will have to visit them and compare the expression which sounds like it could be done a better way – johnny 5 Mar 23 '18 at 16:56
  • @johnny 5, Can you show me a better way to implement `GetPredicate`. I need this function in my component and i can't use lambda Expression because i build that expression dynamically from user input at runtime.(I update the question). – M.Hassan Mar 25 '18 at 06:06
  • @M.Hassan what do you need help? It looks like you’ve already solved your own answer? The better way to do this would avoid the whole problem using oData and use their metadata api so you can control what they filter. – johnny 5 Mar 25 '18 at 12:14
  • @johnny 5, OData isn't an option. The constraint is parsing boolean string expression and return Predicate. Thanks for suggestion. – M.Hassan Mar 27 '18 at 12:38

2 Answers2

1

As suggested in the comments its better to use Dynamic Linq. As find() is the equivalent of Where().FirstOrdefault():

List<T>.AsQueryable().Where("CategoryId = 5 and Price < 10").FirstOrDefault();
FyCyka LK
  • 54
  • 5
1

I used System.Linq.Dynamic which is based on a previous work by MicroSoft

Install-Package System.Linq.Dynamic

I Implemented the following static /Extension methods:

using System;
using System.Collections.Generic;
using DynamicExpression=System.Linq.Dynamic.DynamicExpression; //nuget package
using System.Linq.Expressions;

public static class MyDynamics
{           
    public static Predicate<T> GetPredicate<T>(string stringExpression)
    {        
        var exp = DynamicExpression.ParseLambda<T, bool>(stringExpression).Compile();               
        var predicate = new Predicate<T>(exp);
        return predicate;
    }   
}

How To Use:

Console.WriteLine("------- Find items using string expression ------");     
//use string expression
var predicate = MyDynamics.GetPredicate<Part>("PartId==1444");
//pass  the predicate to List.Find
var part= parts.Find(predicate);
Console.WriteLine("Part: Find: PartId= {0} , PartName={1}",part.PartId, part.PartName);

Life Demo in Fiddle

johnny 5
  • 19,893
  • 50
  • 121
  • 195
M.Hassan
  • 10,282
  • 5
  • 65
  • 84