如何动态创建lambda表达式

Mat*_*ero 8 .net c# lambda

我们假设我有以下课程:

public class Show
{
    public string Language { get; set; }
    public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

根据这些信息,我的目标是创建一个这样的lambda表达式:

g => g.Language == lang && g.Name == name
Run Code Online (Sandbox Code Playgroud)

lang并且name是我想在创建表达式时添加为常量值的局部变量.

如您所见,编译的函数将是类型 Func<Genre, bool>

为了帮助您更清楚地理解,我想实现与此类似的东西:

string lang = "en";
string name = "comedy";
Genre genre = new Genre { Language = "en", Name = "comedy" };
Expression<Func<Genre, bool>> expression = CreateExpression(genre, lang, name);
// expression = (g => g.Language == "en" && g.Name == "comedy")
Run Code Online (Sandbox Code Playgroud)

我知道表达式树的存在,但我对这个主题几乎是新手,所以我甚至不知道如何开始.

这个问题可以解决吗?如何动态创建这样的表达式?

Eri*_*ric 1

public Expression<Func<TValue, bool>> CreateExpression<TValue, TCompare>(TValue value, TCompare compare)
{
    var pv = Expression.Parameter(typeof(TValue), "data");
    var compareProps = typeof(TCompare).GetProperties();

    // First statement of the expression
    Expression exp = Expression.Constant(true);

    foreach (var prop in typeof(TValue).GetProperties())
    {
        // Check if the compare type has the same property
        if (!compareProps.Any(i => i.Name == prop.Name))
            continue;

        // Build the expression: value.PropertyA == "A" 
        // which "A" come from compare.PropertyA
        var eq = Expression.Equal(
            Expression.Property(pv, prop.Name), 
            Expression.Constant(compareProps
                .Single(i => i.Name == prop.Name)
                .GetValue(compare)));

        // Append with the first (previous) statement
        exp = Expression.AndAlso(exp, eq);
    }

    return Expression.Lambda<Func<TValue, bool>>(exp, pv);
}
Run Code Online (Sandbox Code Playgroud)

用法:

var value = new { Lang = "en", Name = "comedy"};

// The compareValue should have the same property name as the value, 
// or the expression will just ignore the property
var compareValue = new { Lang = "en", Name = "comedy", Other = "xyz" };

// The create expression content is
// {data => ((True AndAlso (data.Lang == "en")) AndAlso (data.Name == "comedy"))}
bool isMatch = CreateExpression(value, compareValue).Compile()(value); // true
Run Code Online (Sandbox Code Playgroud)