C # Создание лямбда-выражения динамически - PullRequest
0 голосов
/ 10 октября 2018

Я работаю с Dapper и пытаюсь создать метод автоматического сопоставления для внутреннего соединения.Это пример моделей:

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; }
}

Это запрос:

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

Если я напишу код вручную, я напишу это:

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();  
}

Теперь я хочу динамически создать Func<TFirst, TSecond, TOut>, который мне нужен для отображения объекта.Кто-нибудь может мне помочь?Большое спасибо.PS Я знаю, что в этом случае не имеет смысла создавать его динамически, но это всего лишь простая версия всего проекта автокартирования.

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Посмотрите на PredicateBuilder.http://www.albahari.com/nutshell/predicatebuilder.aspx

Вот какой-то псевдокод

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();
0 голосов
/ 10 октября 2018

РЕШЕНИЕ

Наконец-то я нахожу способ делать то, что хочу.Это код функции, которая генерирует 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();
}

И это метод «GetPage»:

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