C# Create Lambda Expression Dynamically

12,527

Solution 1

SOLUTION

Finally I find the way to do what I want.
This is the code of the function that Generate Func<TFirst, TSecond, TOut>:

public static Func<TFirst, TSecond, TFirst> MappingDynamicFunc<TFirst, TSecond>()
{
    ParameterExpression paramFirst = Expression.Parameter(typeof(TFirst), "paramFirst");
    ParameterExpression paramSecond = Expression.Parameter(typeof(TSecond), "paramSecond");

    MemberExpression memberExpression = Expression.PropertyOrField(paramFirst, "UserCreatedPage");
    BinaryExpression assign = Expression.Assign(memberExpression, paramSecond);

    LabelTarget labelTarget = Expression.Label(typeof(TFirst));
    GotoExpression returnExpression = Expression.Return(labelTarget, paramFirst, typeof(TFirst));
    LabelExpression labelExpression = Expression.Label(labelTarget, Expression.Default(typeof(TFirst)));

    BlockExpression block = Expression.Block(
        assign,
        returnExpression,
        labelExpression
    );

    return Expression.Lambda<Func<TFirst, TSecond, TFirst>>(block, new ParameterExpression[] { paramFirst, paramSecond }).Compile();
}

And this is the "GetPage" method:

public List<Page> GetPage(IDbConnection dbConnection, string sql)
{
    return (List<Page>)dbConnection.Query<Page, User, Page>(sql, 
        MappingDynamicFunc<Page, User>(),
        splitOn: "IdUser").ToList();  
}

Solution 2

Take a look at PredicateBuilder. http://www.albahari.com/nutshell/predicatebuilder.aspx

Here is some pseudo code

var predicate = PredicateBuilder.True<SomeClass>();

if (SomeCondition)
{
     var inner = PredicateBuilder.False<SomeClass>();
         inner = inner.Or(p => p.Category == "WhatEver");
         inner = inner.Or(p => p.Category == "");

     predicate = predicate.And(inner);
}

...

var result = MyIEnumerable<SomeClass>.AsQueryable()
                                     .Where(predicate)
                                     .FirstOrDefault();
Share:
12,527
Fabrizio Pairone
Author by

Fabrizio Pairone

Updated on June 04, 2022

Comments

  • Fabrizio Pairone
    Fabrizio Pairone almost 2 years


    I work with Dapper and I try to create auto-mapped method for inner join.
    This is the example of the models:

    public class User
    {
        public long IdUser { get; set; }
        public string Email { get; set; }
    } 
    
    public class Page
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public long IdUserCreatedPage { get; set; }
        public User UserCreatedPage { get; set; }
    }
    

    This is the query:

    SELECT * FROM "PAGE" INNER JOIN "USER" ON "PAGE"."IdUserCreatedPage" = "USER"."IdUser"
    

    if I write code mannualy I will write this:

    public List<Page> GetPage(IDbConnection dbConnection, string sql)
    {
        return (List<Page>)dbConnection.Query<Page, User, Page>(sql, 
            (Page p, User u) =>
            {
                p.UserCreatedPage = u;
                return p;
            },
            splitOn: "IdUser").ToList();  
    }
    

    Now, what I want is create dynamically the Func<TFirst, TSecond, TOut> that I need for mapping the object.
    Can someone help me? Thank you very much.

    P.S. I know that in this case it does not make sense create it dynamically, but this it's only a simply version of all the project of auto-mapping.