Programatically Converting a Literal into an equivalent Lambda Expression in c#3.0
As part of a project that we are working on at the moment we need a way of converting a literal or constant into a lambda expression which when evaluated will yield the original literal value (in c#). This must work in the same way for multiple types.
For example given the literal string “hello” we need to programmatically create the lambda
() => “hello”
and for the boolean true we want to create:
() => true
etc.
This can be achieved by creating an appropriate expression tree and then compiling it into a lambda expression, and as we want this to work for different types we wrap all of this into a generic function like the following:
static public Func<T> ToLambda<T>(T val)
{
ConstantExpression body = Expression.Constant(val);
LambdaExpression exp = Expression.Lambda<Func<T>>(body, null);
return (Func<T>)exp.Compile();
}
The function takes the value in question as type T and returns a parameter-less delegate of return type T. It uses the passed value to create a ConstantExpression, and then uses it to create a LambdaExpression, as the required lambda has no paramters it passes ‘null’ into the constructor’s second parameter. Now all that is left is to compile the LambdaExpression, this creates and returns the required delegate which is then returned.
The following code shows the lambda generator in action:
static public void TestLiteralToLambda()
{
// Create the Lambda from literal
var boolLambda = ToLambda(true);
// Evaluate the lambda..
bool boolVal = boolLambda();
// and, log out some info
Console.WriteLine(“Lambda evaluates to – {0}”, boolVal);
var stringLambda = ToLambda(“Rainy day in Dublin”);
string stringVal = stringLambda();
Console.WriteLine(“Lambda evaluates to – {0}”, stringVal);
var doubleLambda = ToLambda(3.14159);
double doubleVal = doubleLambda();
Console.WriteLine(“Lambda evaluates to – {0}”, doubleVal); ?
}
So far, so good. Although this might seem a little strange and vaguely useless, what it allows us to do is to treat literals and lambdas of the same type in exactly the same way.
Specifically what we want to be able to do is to define ‘super properties’ on objects whose values when queried are either regular values (as normal) or are the result of evaluating a rule, this rule being provided as a lambda expression. When the property’s value is set the programmer either provides a value (literal or constant) or a rule (lambda expression).
Further details on the exact makeup of these ‘super properties’ elude us at the moment, more later…