Action<Action<string,int>> and Lambda Expression in C# - c#

I've searched on this, but don't really know how to word the question to get the answer so far I can't find anything on nested actions like this with Lambda expressions. I can find lots of help on passing lambda expressions as parameters where the parameter is a delegate and in fact I'm doing that lots in my code. It's the nested lambda expression that's giving me problems.
I have a class with a property of type
Action<Action<string,int>> myAction
and I want to assign it with a Lambda expression. I can do it without Lambda expressions using real methods that I have elsewhere in the code. I can also do something simple like
myAction = ((a) => { a("a string", 0); });
but I would like to asign the sub-action and the action in one Lambda. Something like...
myAction = (((s,i)=>{//sub-action body here})=> { //do something here});
But this syntax doesn't work. Is there a way to do this, or do I have to define my methods in advance and do it without a Lambda expression if I want to do this?

Action<Action<string, int>> myAction = a => (new Action<string, int>((s, i) => Console.WriteLine(i + s)))("hello", 1);
myAction(null); //1hello
Console.ReadLine();
though its equal to
Action<Action<string, int>> myAction = a => Console.Writeline("1hello");
you just ignore an argument

Related

Pass Expression Tree as Method parameter

I have a function:
public void Execute(Expression<Action> expression)
{
var time = expression.Compile().Benchmark();
var msg = string.Format("{0} took {1} to complete",
ReflectionHelper.GetComponentCallDetails().ToString(),
time.ToString(#"hh\:mm\:ss\.ff"));
Logger.Info(msg);
}
The delegate that needs to be called is something like:
channels = GetAllChannelsImpl(maxResults);
I am relatively new to Expression Trees and cannot figure out a way to pass the Action delegate to the method.
I was able to do the same functionality using
public void Execute(Action action)
{
var time = action.Benchmark();
var msg = string.Format("{0} took {1} to complete",
ReflectionHelper.GetComponentCallDetails().ToString(),
time.ToString(#"hh\:mm\:ss\.ff"));
Logger.Info(msg);
}
and calling as
Execute(() =>
{
channels = GetAllChannelsImpl(maxResults);
});
But I wanted to use the Expression Tree based approach in order to eliminate the need to use the overhead of reflection to figure out the details of the method invoked to log it.
Can anyone suggest the right way to pass the expression tree for the above action delegate as a method parameter.
A lambda expression by itself does not have a type. The actual type it takes is inferred by the compiler depending on what you are trying to assign or cast to. With that said, any calls to your Execute() method using simple lambdas will be ambiguous since your lambda would be compatible as an Action or Expression<Action>. You would have to disambiguate this by explicitly casting to the type you expect.
// assign to a variable
Expression<Action> action1 = () => ...;
Execute(action1);
// cast
Execute((Expression<Action>)(() => ...));
// use the constructor
Execute(new Expression<Action>(() => ...));
It would be better IMHO to remove the ambiguous overload and rename one of the methods. I'd recommend renaming the expression overload to ExecuteExpression().

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.

Please guide me in getting the following line c# lambda expression code

<%= MyClass.GetData(() => new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode") })%>
Can someone please explain me what the MyClass.GetData method is getting passed as parameter?
I don't expect a full explanation and i know that i should learn further into anonyous methods and lamda expression... But for now can you explain what the the code as from "() =>......." means?
And if you know some nice articles that builds towards understanding material like this that would be cool !
The () => new [] { ... } is a lambda expression which is short-hand syntax for an anonymous delegate. This means that you are passing in essentially the equivalent of a pointer to a function that takes no arguments, the () part indicates the arguments, and returns the results in { } braces (Html.TextBox.... etc).
Essentially, this would be equivalent to passing a method name that accomplishes the same thing, but it's more concise syntax:
MyClass.GetData(() => new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode") }
is the same, roughly, as creating a method, then passing that method name in.
private WebControl[] GetControls()
{
return new[] { Html.TextBox(prefix + "Postcode", Customer.ZipCode, new { maxlength = 7 }), Html.ValidationIcon(prefix + "ZipCode");
}
....
MyClass.GetData(GetControls);
p.s. Here's a good basic lambda tutorial: http://blogs.msdn.com/b/ericwhite/archive/2006/10/03/lambda-expressions.aspx
() => means an lambda that does not take any parameters. So you are passing into GetData a lambda that takes no parameters and returns a new array.
It means: Here is an anonymous delegate that takes no argument and returns an array of objects whose type will be inferred from the return values of Html.TextBox() and Html.ValidationIcon().

What is the outcome of "() => true"

I'm reviewing another person's code and can't ask him... What does that line of C# code do?
It's a lambda expression that takes no parameter and returns true.
The equivalent anonymous delegate is:
delegate() { return true; };
Most likely the method requires a parameter of type Func<bool>, which is a generic delegate with the same signature as above code.
EDIT:
As noted by cdhowie, the above lambda can also be evaluated to an expression tree of type Expression<Func<bool>>.
Here's the equivalent expression tree:
var body = Expression.Constant(true);
Expression<Func<bool>> returnsTrueExpression = Expression.Lambda<Func<bool>>(body);
You can 'convert' it to an actual delegate by calling Compile()
Func<bool> returnsTrueFunc = returnsTrueExpression.Compile();
This is a lambda expression that always return true. This is a delegate that has functionality similar to this method
bool Test(){
return true;
}
The code reminds me of when you may want to stub or mock values in the early stages of creating unit tests.
You could have a class that has a method like:
bool result = SomeClass.RunSomeImportantProcess(Func<bool> process)
and in your tests you might want to do something as a stub like
Assert.IsTrue(SomeClass.RunSomeImportantProcess(() => true));
Its a lambda expression which doesn't take any parameter but returns true. Whether its required or not, you would have to provide more info to determine.

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