You can in fact do this, but the type becomes unknown. The object returned from this method will be of the proper type Expression<Func<Test, string>>
but cannot be strong typed at compile time:
static LambdaExpression CreateExpression<TModel>(string propertyName)
{
var t = typeof(TModel);
var param = Expression.Parameter(typeof(TModel), "x");
//get the type for the 2nd generic arg
var propType = t.GetProperty(propertyName).PropertyType;
//make the generic type Func<TModel, TProp>
Type genericFuncType = typeof(Func<,>).MakeGenericType(new Type[] { typeof(TModel), propType });
//get the Expression.Lambda method
MethodInfo mi = typeof(Expression).GetMethods().First(a => a.Name == "Lambda" && a.GetParameters().Length == 2);
//get the Expression.Lambda<Func<TModel, TProp>> method
MethodInfo mi2 = mi.MakeGenericMethod(new Type[] { genericFuncType });
//Call Expression.Lambda<Func<TModel, TProp>>
return (LambdaExpression)mi2.Invoke(null, new object[] { Expression.PropertyOrField(param, propertyName), new ParameterExpression[] { param }});
}
However note that the return type is now somewhat unknown and will need cast to use (or use dynamic).
So now you need even more code to cast it. Perhaps this would be useful in some sort of factory or such - not sure your use case.
class Program
{
public static void Main(string[] args)
{
var theExpression = CreateExpression<Test>("Name");
var theExpressionStrongType = theExpression as Expression<Func<Test, string>>;
//now you could use theExpressionStrongType
//or do this and go wild. :)
dynamic d = theExpression;
Console.ReadKey();
}
}
class Test
{
public string Name { get; set; }
}
Disclaimer: if you seriously want to use this in a production environment, I would clean up the code a LOT to just get refection types once, etc, etc...