我们假设我有以下课程:
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)
我知道表达式树的存在,但我对这个主题几乎是新手,所以我甚至不知道如何开始.
这个问题可以解决吗?如何动态创建这样的表达式?
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)