Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement method with expression parameter c#

Tags:

c#

.net

linq

I want to create a method like this:

var result = database.Search<EntityType>(x=>x.Name, "Entity Name field value");
result = database.Search<EntityType>(x=>x.Id, "Entity Id field value");
result = database.Search<EntityType2>(x=>x.Id, "Entity2 Id field value");
result = database.Search<EntityTypeAny>(x=>x.FieldAny, "EntityAny FieldAny value");

How can I implement this method?

like image 295
Nodir Avatar asked May 08 '13 09:05

Nodir


2 Answers

You can turn a selector and value into a predicate using Expression.Equal:

static IQueryable<TSource> Search<TSource, TValue>(
    this IQueryable<TSource> source,
    Expression<Func<TSource,TValue>> selector,
    TValue value)
{
    var predicate = Expression.Lambda<Func<TSource,bool>>(
        Expression.Equal(
            selector.Body,
            Expression.Constant(value, typeof(TValue))
        ), selector.Parameters);
    return source.Where(predicate);
}

Then you just need to do something like:

var result = database.SomeEntities.Search(x => x.SomeProp, "value");

If you want to do it from the database, then that depends on what the database is; for example, with LINQ-to-SQL you could add an additional method:

static IQueryable<TSource> Search<TSource, TValue>(
    this System.Data.Linq.DataContext database,
    Expression<Func<TSource, TValue>> selector,
    TValue value) where TSource : class
{
    IQueryable<TSource> source = database.GetTable<TSource>();
    return Search(source, selector, value);
}

and use:

var result = database.Search<SomeEntity, string>(x => x.SomeProp, "value");

frankly I think it is clearer to use the database.SomeEntities version, though.

like image 64
Marc Gravell Avatar answered Sep 20 '22 17:09

Marc Gravell


I can only think of this (with 2 generic arguments)

    public static IEnumerable<TModel> Search<TModel, TValue>(
        Expression<Func<TModel, TValue>> expression,
        TValue value
    )
    {
        return new List<TModel>();
    }

usage

var result = Search<EntityType, int>(x => x.Id, 1);
var result2 = Search<EntityType, string>(x => x.Name, "The name");

you can replace TValue with object to avoid the second generic argument, but I would stick with this.

Btw. this works great in conjunction with this little helper

public static class ExpressionHelpers
{
    public static string MemberName<T, V>(this Expression<Func<T, V>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression == null)
            throw new InvalidOperationException("Expression must be a member expression");

        return memberExpression.Member.Name;
    }
}

Now you can get the Name of the Property (Id oder Name) in this example by calling

var name = expression.MemberName();
like image 44
Jürgen Steinblock Avatar answered Sep 21 '22 17:09

Jürgen Steinblock