Let's suppose I have the following class:
public class Show
{
public string Language { get; set; }
public string Name { get; set; }
}
Based on this information, my goal is to create a lambda expression like this:
g => g.Language == lang && g.Name == name
lang
and name
are local variables I would like to add as constant values when creating the expression.
As you can see, the compiled function would be of type Func<Genre, bool>
To help you understand more clearly, I would like to achieve something similar to this:
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")
I am aware of the existence of expression trees but I'm pretty much new to this topic so I don't even know how to start.
Can this problem be solved? How can I create such expression dynamically?
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);
}
Usage:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With