You can use interfaces in order to create a Func against the interface who has defined the necessary properties.
Example:
interface IExpressionable {
string Language { get;set; }
string Name { get;set; }
}
class Genre : IExpressionable {
string Language {get;set;}
string Name {get;set;}
}
Genre genre = new Genre();
Expression<Func<IExpressionable, bool>> expression = CreateExpression(genre, lang, name);
expression = (g => g.Language == "en" && g.Name == "comedy")
An alternative implementation of this concept can be had by providing a GetLanguage and GetName method on your interface, which would force subscribers to implement the underlying methods in order to return a "Language" and "Name" based on their own internal methods.
interface IExpressionable {
string GetExpressionOne();
string GetExpressionTwo();
}
class Genre : IExpressionable {
string Language {get;set;}
string Name {get;set;}
public string GetExpressionOne() {
return Language;
}
public string GetExpressionOne() {
return Name;
}
}
class SomethingElse {
string Orange {get;set;}
string BananaPeel {get;set;}
public string GetExpressionOne() {
return Orange;
}
public string GetExpressionOne() {
return BananaPeel;
}
}
Genre genre = new Genre();
SomethingElse else = new SomethingElse();
Expression<Func<IExpressionable, bool>> expression = CreateExpression(genre, lang, name);
Expression<Func<IExpressionable, bool>> expression2 = CreateExpression(else, lang, name);
expression = (g => g.GetExpressionOne() == "en" && g.GetExpressionTwo() == "comedy");
Edit from your comment above: @kaveman I only have the key values, but I can fetch the key properties via reflection using some custom attributes that I defined. In this example, Language and Name would be decorated with an attribute that defines them as key properties
My answer is to avoid this thought completely. Create an interface that defines the methods you need to perform whatever expression you are looking for, and have the entities inherit from it. You could have your methods on the interface be "GetKeyOne" and "GetKeyTwo". Then your expression doesn't have to be dynamic, you just need to define what the expression does when it is interacting with KeyOne and KeyTwo, which is defined in each implementor.