What is the best way to ReadLine by Expression Tree? - c#

If I want to get a user input from Console to my Expression Tree. What is the best way to do it? and how to make variable 'name' duck typing?
Here are my code.
using System;
using System.Reflection;
using System.Collections.Generic;
using Microsoft.Linq;
using Microsoft.Linq.Expressions;
namespace ExpressionTree
{
class Program
{
static void Main(string[] args)
{
List<Expression> statements = new List<Expression>();
// Output
MethodInfo Write = typeof(System.Console).GetMethod("Write", new Type[] { typeof(string) });
ConstantExpression param = Expression.Constant("What is your name? ", typeof(string));
Expression output = Expression.Call(null, Write, param);
statements.Add(output);
// Input
MethodInfo ReadLine = typeof(System.Console).GetMethod("ReadLine");
ParameterExpression exprName = Expression.Variable(typeof(String), "name");
Expression exprReadLine = Expression.Call(null, ReadLine);
// .NET 4.0 (DlR 0.9) from Microsoft.Scripting.Core.dll
// Expression.Assign and Expression.Scope
ScopeExpression input = Expression.Scope(Expression.Assign(exprName, exprReadLine), exprName);
statements.Add(input);
// Create the lambda
LambdaExpression lambda = Expression.Lambda(Expression.Block(statements));
// Compile and execute the lambda
lambda.Compile().DynamicInvoke();
Console.ReadLine();
}
}
}

Expression trees are designed to perform a fixed operation - in particular, the member-access is going to want a known MemberInfo (etc) at the point of expression tree creation (since they are immutable).
You could duplicate the generated code from dynamic if you are playing with 4.0, but to be honest, the better approach in this scenario is simply: don't use an expression tree.
Either reflection or ComponentModel (TypeDescriptor) would be ideal for this dynamic access to a member.
Also - calling Compile on something you use only once isn't saving any time, and using DynamicInvoke isn't either... you need to use the typed delegate form (Invoke).

Related

Does the LINQ Expression API offer no way to create a variable?

I want to validate my assumption that the LINQ Expression API does not have any means for us to create an expression that represents the creation of a local variable.
In other words, you cannot create an expression to represent:
int local;
since that is a variable declaration statement, and the API does not support statement lambdas. The only state that a lambda expression, as represented by the LINQ Expression API (and not a delegate instance) can work with is parameters it receives and the captured variables it receives via a closure.
Is my assumption (based on a few months of practice of the LINQ Expression API) correct?
False. There are some overloads of Expression.Block to do it.
What is true is that you can't create a lambda expression through the use of the C# compiler that has a variable, but that is a limitation of the compiler.
So you can't
Expression<Func<int>> exp = () => {
int v = 1;
return v;
};
but you can
var variable = Expression.Variable(typeof(int));
var lambda = Expression.Lambda<Func<int>>(
Expression.Block(
new[] { variable },
Expression.Assign(variable, Expression.Constant(1)),
variable)); // With lambda expressions, there is an implicit
// return of the last value "loaded" on the stack
since that is a variable declaration statement, and the API does not support statement lambdas.
This was true in .NET < 4.0 . In .NET 4.0 Microsoft added Expression methods to build nearly everything that can be present in the body of a method (there are some missing "things", like unsafe code keywords/operators, plus there are the primitives but there aren't complex constructs like the for or lock, that can be built on top of other constructs). Note that 90% of those added things are incompatible with LINQ-to-SQL/EF.
Well, you can use Expression.Block to declare a block which contains local variables...
For example:
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
var x = Expression.Variable(typeof(int), "x");
var assignment1 = Expression.Assign(x, Expression.Constant(1, typeof(int)));
var assignment2 = Expression.Assign(x, Expression.Constant(2, typeof(int)));
var block = Expression.Block(new[] { x }, new[] { assignment1, assignment2 });
}
}
That builds an expression tree equivalent to:
{
int x;
x = 1;
x = 2;
}
The C# compiler doesn't use this functionality within lambda expression conversions to expression trees, which are currently still restricted to expression lambdas, as far as I'm aware.

Optimize MethodInfo.Invoke when method info is only known at runtime

I am using reflection to call methods, and invoking the methods using Invoke() doesn't do it for me, too slow. I generate thousands - millions of method calls, it is a test automation tool. At compile time I have no clue about the method name, parameter type(s) or return type. So Jon Skeet's article on using delegates to cache reflection is no help here.
Here is what I have:
foreach (MethodInfo method in _methods)
{
foreach (var p in method.GetParameters())
{
var paramValue = Utils.RandomizeParamValue(p.ParameterType.Name);
parameters.Add(paramValue);
}
var result = method.Invoke(_objectInstance, parameters.ToArray());
//_objectInstance is the class instance of which the method is a member of.
}
I have researched the DLR (ExpandoObject, DynamicObject) but I am not sure it has what I am looking for. What I am looking for is a way to bypass the overhead of reflection, or cache method invocations, even if it turns out be an ugly hack. Is there a common hack that I have missed? Could I go down to IL level and do some tricks there?
One option is to use expression tree to build delegate that will call your methods. MSDN have introduction in Expression Trees article and in particular you'll need MethodCallExpression
Create an expression sample (from MethodCallExpression article):
string[,] gradeArray =
{ {"chemistry", "history", "mathematics"}, {"78", "61", "82"} };
var arrayExpression = Expression.Constant(gradeArray);
// Create a MethodCallExpression that represents indexing
// into the two-dimensional array 'gradeArray' at (0, 2).
// Executing the expression would return "mathematics".
var methodCallExpression = Expression.ArrayIndex(
arrayExpression,
Expression.Constant(0),
Expression.Constant(2));
Compile an expression to delegate sample (from main article):
Expression<Func<int, bool>> expr = num => num < 5;
Func<int, bool> result = expr.Compile();
Console.WriteLine(result(4));

Moq and reflection, passing dynamically generated expression tree / lambda to moq

Is it possible to write code like the following. I'm trying to using Moq with objects that I'm reflecting on as part of a testing framework. The code below raises a "Unhandled expression type: 'Goto'" exception from Moq, which I guess is expecting something different. It kind of looks like it should work though!
private void button1_Click(object sender, EventArgs e)
{
Ifoo = foo Foo();
// Create input parameter for lambda
ParameterExpression value = Expression.Parameter(typeof(IFoo), "value");
// create return statement for lambda
Expression setupProperty = Expression.Return(Expression.Label(), Expression.Property(value, "Bar"), typeof(string));
// convert expression to lambda (should now be the equivalent of "v => v.Bar")
var func = Expression.Lambda<Func<IFoo, string>>(setupProperty, value);//.Compile();
//string s = func(foo); // this bit works fine if .Compile() is included
var mockFoo = new Mock<IFoo>();
mockFoo.SetupProperty(func); // exception thrown by moq here, obviously isn't exactly the same as "v => v.Bar"
mockFoo.Object.Bar = "Burge+";
}
Thanks!
Ok, this is possible, here is the corrected code.
// Create input parameter for lambda
ParameterExpression value = Expression.Parameter(typeof(IFoo), "value");
// create return statement for lambda
Expression setupProperty = Expression.Property(value, "Bar");
// convert expression to lambda (should now be the equivalent of "v => v.Bar")
var func = Expression.Lambda<Func<IFoo, string>>(setupProperty, value);
var mockFoo = new Mock<IFoo>();
mockFoo.SetupProperty(func); // this works now
mockFoo.Object.Bar = "Burge+";
I investigated this by creating an expression from a lambda using the code below
Expression<Func<IFoo, string>> setupBar = v => c.Bar;
I then looked at this in the debugger in vs 2010. Expressions have a "Debug View" that shows a text representation of the expression so it is possible to add a watch on that or something similar. The above comes out as
.Lambda #Lambda1<System.Func`2[WindowsFormsApplication1.IFoo,System.String]>(WindowsFormsApplication1.IFoo
$v) {
$v.Bar
}
I looked at this and tried to work out what Expressions would make this, then created an expression and compared it in the debugger.
The interesting thing for me is that although this expression returns a value there is no assignment or return statement. I guess this must be implicit somehow.

How would I add type specific implementations to linq binary expressions?

I have a fairly simple expression parser that uses the Linq.Expression namespace.
Input is something like: (1+1), it finds the left and right constants, and converts the operator char to an ExpressionTypes enum value, creates the appropriate expression, compiles and executes.
I'd really like to be able to do string manipulations, (abc+def) would evaluate to abcdef for instance, however:
System.InvalidOperationException: The binary operator Add is not defined for the types 'System.String' and 'System.String'
How would I go about implementing this myself?
Something like the equavlant to an ExpressionTypes.Concat would be ideal.
You have to create the MethodCallExpression yourself, which in this case is for the static method string.Concat. (This is what the compiler does itself when you compile such code)
Here's some code that demonstrates using MethodInfo to extend the definition of the binary expression Add to concatenation of strings.
One example uses the existing Concat method in the String type.
The second example uses a custom Concat method in the Program type (the class this is all embedded in):
private MethodInfo ConcatMethod = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
private MethodInfo ConcatMethod2 = typeof(Program).GetMethod("Concat", new Type[] { typeof(string), typeof(int) });
public static string Concat(string obj1, int obj2)
{
return string.Concat(obj1, obj2.ToString());
}
private Expression SomeCode(string leftStr, string rightStr)
{
Expression left = Expression.Constant(leftStr);
Expression right = Expression.Constant(rightStr);
return Expression.Add(left, right, ConcatMethod);
}
private Expression SomeCode(string leftStr, int rightInt)
{
Expression left = Expression.Constant(leftStr);
Expression right = Expression.Constant(rightInt);
return Expression.Add(left, right, ConcatMethod2);
}
static void CheesyTest2()
{
Program foo = new Program();
Expression exp = foo.SomeCode("abc", "def");
LambdaExpression lambdaExpression = Expression.Lambda(exp);
Delegate func = lambdaExpression.Compile();
object result = func.DynamicInvoke();
Console.WriteLine(string.Format("Expression result: {0}", result));
exp = foo.SomeCode("abc", 42);
lambdaExpression = Expression.Lambda(exp);
func = lambdaExpression.Compile();
result = func.DynamicInvoke();
Console.WriteLine(string.Format("Expression2 result: {0}", result));
}
For custom operators it's actually a method call so you need to find the corresponding method and create the expression tree for calling that method. Haven't work much with expression trees so im affraid I can't give you a code sample but I hope this Helps none the less

Replacing parameters in a lambda expression

I had a part of code that takes in lambda expressions at runtime, which I can then compile and invoke.
Something thing;
Expression<Action<Something>> expression = (c => c.DoWork());
Delegate del = expression.Compile();
del.DynamicInvoke(thing);
In order to save execution time, I stored those compiled delegates in a cache, a Dictionary<String, Delegate> which the key is the lambda expression string.
cache.Add("(Something)c => c.DoWork()", del);
For exact same calls, it worked fine. However I realized that I could receive equivalent lambdas, such as "d => d.DoWork()", which I should actually use the same delegate for, and I wasn't.
This got me wondering if there was a clean way (read "not using String.Replace", I already did that as a temporary fix) to replace the elements in a lambda expression, like maybe replacing them by arg0 so that both
(c => c.DoWork()) and (d => d.DoWork())
are transformed and compared as (arg0 => arg0.DoWork()) by using something fuctionnally similar to injecting a Expression.Parameter(Type, Name) in a lambda.
Is that possible ? (Answers can include C#4.0)
I used strings, since it was the easisest way for me. You can't manually change the name of the parameter expression (it has the "Name" property, but it is read-only), so you must construct a new expression from pieces. What I did is created a "nameless" parameter (actually, it gets an autogenerated name in this case, which is "Param_0") and then created a new expression almost the same as the old one, but using the new parameter.
public static void Main()
{
String thing = "test";
Expression<Action<String>> expression = c => c.ToUpper();
Delegate del = expression.Compile();
del.DynamicInvoke(thing);
Dictionary<String, Delegate> cache = new Dictionary<String, Delegate>();
cache.Add(GenerateKey(expression), del);
Expression<Action<String>> expression1 = d => d.ToUpper();
var test = cache.ContainsKey(GenerateKey(expression1));
Console.WriteLine(test);
}
public static string GenerateKey(Expression<Action<String>> expr)
{
ParameterExpression newParam = Expression.Parameter(expr.Parameters[0].Type);
Expression newExprBody = Expression.Call(newParam, ((MethodCallExpression)expr.Body).Method);
Expression<Action<String>> newExpr = Expression.Lambda<Action<String>>(newExprBody, newParam);
return newExpr.ToString();
}
There's more to a lambda expression than just the text. Lambdas are re-written by the compiler into something much more complicated. For example, they may close over variables (which could include other delegates). This means that two lambdas could look exactly the same, but perform completely different actions.
So you might have luck caching your compiled expression, but you need to give them a more meaningful name for the key than just the text of the expression. Otherwise no amount of argument substitution will help you.

Categories