.NET - dump statement lambda body to string - c#

Given the following statement lambda example:
var fMyAction = new Action(() =>
{
x += 2;
something = what + ever;
});
What are possible ways to get the body of that lambda and dump it to string? (Something that will ultimately allow to write an extension method for Action class of this kind: fMyAction.Dump() which will return "x += 2; something = what + ever;").
Thanks

It's not possible in that form. Your lamda gets compiled to byte-code. While in theory it's possible to decompile the byte-code, just like reflector does, it's difficult, error prone and doesn't give you the exact code you compiled, but just code that's equivalent.
If you use an Expression<Action> instead of just Action you get the expression tree describing the lamda. And converting an expression tree to a string is possible(and there are existing libraries which do it).
But that's not possible in your example because it's a multi statement lamda. And only simple lamdas can be automatically converted to an expression tree.

Read through the tutorial here,
http://blogs.msdn.com/b/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx
Pay close attention to the visitor pattern he uses to walk a given expression tree. You should be able to alter it to fit your needs easy enough.

Related

Can Roslyn be used to generate dynamic method similar to DynamicMethod IL generation

I have been using DynamiMethod to generate the IL using
method.GetILGenerator();
This works well but is of course very hard to use since you generally don't want to work with low level IL in a high level language like C#. Now since there is Roslyn I though I can use that instead. I have tried to figure out how to use Roslyn to do similar thing: generate a dynamic method and then create a delegate for it. The only way I was able to do that is to have full class like this
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(#"
using System;
namespace RoslynCompileSample
{
public class Writer
{
public void Write(string message)
{
Console.WriteLine(message);
}
}
}");
Then instead of the Write method I can insert my method inside using string concatenation. After that dynamic assembly is generated in memory and loaded and reflection is used to get the required method and generate the delegate.
This method seems to work fine but seems a bit of an overkill for my case as I will need to use multiple independent methods possible leading to lots of assemblies being loaded.
So the question is: Is there an easy way to do something similar to dynamic method for Roslyn, so that I can only define a body of the method attached to a type? If not, is there any big drawback in compiling many dynamic assemblies (like too many can't be loaded, etc...)
You can use CSharpScript class. await CSharpScript.EvaluateAsync("1 + 2") just evaluates the expression. You can find it in Microsoft.CodeAnalysis.Scripting.CSharp package (currently only prerelease version). Add usings and assembly references using ScriptOptions (second parameter).
Compile expression to delegate:
var func = CSharpScript.Create<int>("1 + 3").CompileToDelegate()
Passing something to the function using globals object:
await CSharpScript.Create<int>("1 + x",
ScriptOptions.Default.AddReferences(typeof(Program).Assembly),
globalsType: typeof(ScriptGlobals))
.CreateDelegate()
.Invoke(new ScriptGlobals() { x = 4 });
I have one more idea how to solve your problem, that does not use Roslyn at all. You described it's annoying to emit IL using ILGenerator. However .NET Framework has build-in semantic trees, that can be compiled to dynamic methods. They live in Linq.Expression namespace and are also used in Linq providers.
var parameter = Expression.Parameter(typeof(int), "a"); // define parameter
var body = Expression.Add(parameter, Expression.Constant(42)); // sum parameter and number
var lambdaExpression = Expression.Lambda<Func<int, int>>(new[] { parameter }, body); // define method
var add42Delegate = lambdaExpression.Compile(); // compile to dynamic method
You can do almost anything using it, it's much more comfortable than ILGenerator and is included in standard library.
I'd like to comment on exyi's answer with Expression and Func<int,int>, but I don't have enough reputation. So here comes my "answer" instead.
If all you need is an first-class citizen piece of code that you can execute with parameters, you can simply create the Lambda like this:
Func<int, int> add42 = number => number + 42;
// Called like this:
int theNumber46 = add42.Invoke(4);
If you need to have the actual expression tree, there is a neat shortcut as well:
Expression<Func<int, int>> add42 = number => number + 42;
// Called like this:
int theNumber46 = add42.Compile().Invoke(4);
The only difference in code is, that you wrapped the Func<int,int> with an Expression<..>. The conceptual difference is, that a Lambda (or Func<> in this example, but there are other Lambdas as well) can be executed as is, whereas an Expression<> needs to be compiled first with the Compile() method. But the Expression holds information about the syntax tree and can therefore be used for IQueryable data providers as used in Entity Framework.
So it all depends on what you want to do with your dynamic method/lamda/delegate.

Need a method to obtain code that would construct a given expression tree

There are two ways to construct an expression tree in C#:
let the compiler rewrite a lambda and store the result;
construct it piecewise, calling factory methods provided by the Expression class.
The first approach is simple, but it doesn't let me integrate already existing subexpressions into a resulting expression, which is my main goal. (These subs are passed to me as function parameters by design).
In fact, the second approach itself is the subexpression composition process, but it is very cumbersome for anything but the simplest expressions with little to no nesting involved.
So, to get the best of two ways, while having to construct the trees piecewise, I look at copiler-generated expressions, and use them as hints. What I do is: write the code to construct a tree, while looking at the given tree. The whole process is quite a routine, so I wonder:
are there tools to automate that? Couldn't find any myself.
aside from codegens, are there some other possibilities to improve my method and make it more productive?
Here's the explaination of why I need this strange process at all.
Expression<Func<IEnumerable<N>, IEnumerable<N>, IEnumerable<N>>>
MyExpression = (src1, src2) =>
src1.SelectMany(outer => lookup[outer.Value1].Select(
inner => new N(outer, inner)));
Now, I am provided with two subexpressions, which are to be placed instead of outer.Value1 and new N(outer, inner). I can't use .Compile() and utilise them as lambdas, because I have to provide the complete expression tree for further processing intact. I need a way to integrate them into MyExpression, and the only method I'm aware of is to construct the whole tree via Expression factories. But with more complex queries it gets extremely complex and error-prone.
aside from codegens, are there some other possibilities to improve my method and make it more productive?
Basically you'd want to write a class that extends ExpressionVisitor that replaces some component of one expression with pieces from the other expression.
are there tools to automate that?
LINQKit does just that. From the website's examples:
Expression<Func<Purchase,bool>> criteria1 = p => p.Price > 1000;
Expression<Func<Purchase,bool>> criteria2 = p => criteria1.Invoke (p)
|| p.Description.Contains ("a");
Console.WriteLine (criteria2.Expand().ToString());
Output:
p => ((p.Price > 1000) || p.Description.Contains("a"))

How to create dynamic lambda based Linq expression from a string in C#?

I'm having some difficulty creating Lambda-based Linq expressions from a string. Here is my basic case using this sample object/class:
public class MockClass
{
public string CreateBy { get; set; }
}
Basically I need to convert a string like this:
string stringToConvert = “x => x.CreateBy.Equals(filter.Value, StringComparison.OrdinalIgnoreCase”;
Into a to predicate/linq expression:
System.Linq.Expressions.Expression<Func<T, bool>> or in this example
System.Linq.Expressions.Expression<Func<MockClass, bool>>
So it is equivalent to the Linq expression inside of the Where method below:
query = query.Where(x => x.CreateBy.Equals(filter.Value,
StringComparison.OrdinalIgnoreCase));
I've tried using the following helpers but can't seem to figure out how to get them to work in this type of case where I want to be able to build a linq expression from string that is not know ahead of time:
http://www.albahari.com/nutshell/predicatebuilder.aspx
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx (it’s now available as a NuGet package as well called “DynamicQuery”)
A similar question was asked here:
Is there an easy way to parse a (lambda expression) string into an Action delegate?
As I understand it, this 'Dynamic Query' is actually a framework for passing in restrictions for a Where clause without using a lambda expression.
The significance of that is that lambda expressions are not dynamic methods, they're anonymous methods. If you ever take a look in an assembly, you'll see that your lambda expressions are converted into closures with any free variables as fields. The class has a method with a signature matching yours, field variables are assigned at the point of invocation.
One good way to think about that is that it implies that your lambda expression is interpreted by the c# compiler at compile-time, and variables are resolved by instantiating an object from this class at run-time.
To demonstrate this, consider the following:
var myLambda = x => x * x
You'll notice this doesn't work. That's because, in order to create the related class/method, the compiler must know, at compile-time, the type of x.
All of this is important because the notion of a lambda expression doesn't exist at the CLR at run-time (in the same form it is in code). A string that looks like a lambda expression is exactly that...

Is there an easy way to parse a (lambda expression) string into an Action delegate?

I have a method that alters an "Account" object based on the action delegate passed into it:
public static void AlterAccount(string AccountID, Action<Account> AccountAction) {
Account someAccount = accountRepository.GetAccount(AccountID);
AccountAction.Invoke(someAccount);
someAccount.Save();
}
This works as intended...
AlterAccount("Account1234", a => a.Enabled = false);
...but now what I'd like to try and do is have a method like this:
public static void AlterAccount(string AccountID, string AccountActionText) {
Account someAccount = accountRepository.GetAccount(AccountID);
Action<Account> AccountAction = MagicLibrary.ConvertMagically<Action<Account>>(AccountActionText);
AccountAction.Invoke(someAccount);
someAccount.Save();
}
It can then be used like:
AlterAccount("Account1234", "a => a.Enabled = false");
to disable account "Account1234".
I've had a look at the linq dynamic query library, which seems to do more or less what I want but for Func type delegates, and my knowledge of Expression trees etc isn't quite good enough to work out how to achieve what I want.
Is there an easy way to do what I want, or do I need to learn expressions properly and write a load of code?
(The reason I want to do this is to allow an easy way of bulk updating account objects from a powershell script where the user can specify a lambda expression to perform the changes.)
The Dynamic LINQ library is a fine choice, as it'll generate expressions you can compile to code in a lightweight fashion.
The example you provided actually produces a boolean -- so you should be able to ask for a Func and it might sort it out.
Edit: This of course is wrong, as Expressions don't have assignment in them at all.
So, another potential way is to take two lambdas. One to find the property you want, one to provide a value:
(a => a.AccountId), (a => true)
Then use reflection to set the property referenced in the first lambda with the result of the second one. Hackish, but it's still probably lightweight compared to invoking the C# compiler.
This way you don't have to do much codegen yourself - the expressions you get will contain most everything you need.
You may try this: Dynamic Lambda Expressions Using An Isolated AppDomain
It compiles a lambda expression using CodeDOM compiler. In order to dispose the in-memory assembly that gets created, the compiler runs on an isolated AppDomain. For the passing the expression through the domain boundary, it has to be serialized. Alas, Expression<> is not Serializable. So, a trick has to be used. All the details are explained in the post.
I'm the author of that component, by the way. I would like very much to hear your feedback from it.
There is no general way to parse a string into a lambda expression without a full compilation, because lambda expressions can reference things that are defined outside the lambda expression. I know of no library that handles the specific case you want. There's a long discussion of this on a thread on a C# discussion group.
The easiest way to get what you want is to compile a method at runtime. You can write a function that takes in the string "a.Enabled = true; return a;" and sticks that in the middle of a function that takes an Account as a parameter. I would use this library as a starting point, but you can also use the function mentioned on another thread.
That's easy:
Use CodeDom to generate the module containing the "surrounding class" you'll use to build the expression; this class must implement the interface known to your application
Use CodeSnippedExpression to inject the expression into its member.
Use Activator type to create the instance of this class in runtime.
Basically, you need to build the following class with CodeDom:
using System;
using MyNamespace1;
using ...
using MyNamespace[N];
namespace MyNamespace.GeneratedTypes
{
public class ExpressionContainer[M] : IHasAccountAction
{
public Action<Account> AccountAction {
get {
return [CodeSnippedExpression must be used here];
}
}
}
}
Assuming that IHasAccountAction is:
public IHasAccountAction {
public Action<Account> AccountAction { get; }
}
If this is done, you can get the expression compiled from string with ease. If you need its expression tree representation, use Expression<Action<Account>> instead of Action<Account> in generated type.

Adding functonality to Linq-to-SQL objects to perform common selections

In a previous question I asked how to make "Computed properties" in a linq to sql object. The answer supplied there was sufficient for that specific case but now I've hit a similar snag in another case.
I have a database with Items that have to pass through a number of Steps. I want to have a function in my database that retrieves the Current step of the item that I can then build on. For example:
var x = db.Items.Where(item => item.Steps.CurrentStep().Completed == null);
The code to get the current step is:
Steps.OrderByDescending(step => step.Created).First();
So I tried to add an extension method to the EntitySet<Step> that returned a single Step like so:
public static OrderFlowItemStep CurrentStep(this EntitySet<OrderFlowItemStep> steps)
{
return steps.OrderByDescending(o => o.Created).First();
}
But when I try to execute the query at the top I get an error saying that the CurrentStep() function has no translation to SQL. Is there a way to add this functionality to Linq-to-SQL in any way or do I have to manually write the query every time? I tried to write the entire query out first but it's very long and if I ever change the way to get the active step of an item I have to go over all the code again.
I'm guessing that the CurrentStep() method has to return a Linq expression of some kind but I'm stuck as to how to implement it.
The problem is that CurrentStep is a normal method. Hence, the Expression contains a call to that method, and naturally SQL cannot execute arbitrary .NET methods.
You will need to represent the code as an Expression. I have one in depth example here: http://www.atrevido.net/blog/2007/09/06/Complicated+Functions+In+LINQ+To+SQL.aspx
Unfortunately, the C# 3.0 compiler has a huge omission and you cannot generate calls to Expressions. (i.e., you can't write "x => MyExpression(x)"). Working around it either requires you to write the Expression manually, or to use a delegate as a placeholder. Jomo Fisher has an interesting post about manipulating Expression trees in general.
Without actually having done it, the way I'd probably approach it is by making the CurrentStep function take the predicate you want to add ("Completed == null"). Then you can create a full Expression> predicate to hand off to Where. I'm lazy, so I'm going to do an example using String and Char (String contains Chars, just like Item contains Steps):
using System;
using System.Linq;
using System.Linq.Expressions;
class Program {
static void Main(string[] args) {
Console.WriteLine(StringPredicate(c => Char.IsDigit(c)));
var func = StringPredicate(c => Char.IsDigit(c)).Compile();
Console.WriteLine(func("h2ello"));
Console.WriteLine(func("2ello"));
}
public static Expression<Func<string,bool>> StringPredicate(Expression<Func<char,bool>> pred) {
Expression<Func<string, char>> get = s => s.First();
var p = Expression.Parameter(typeof(string), "s");
return Expression.Lambda<Func<string, bool>>(
Expression.Invoke(pred, Expression.Invoke(get, p)),
p);
}
}
So "func" is created by using StringPredicate to create an Expression. For the example, we compile it to execute it locally. In your case, you'd pass the whole predicate to "Where" so it gets translated to SQL.
The "get" expression is where you put your "extension" stuff (OrderByWhatever, First, etc.). This is then passed in to the predicate that's given to you.
Don't worry if it looks complicated; it sorta is at first. If you haven't done this kinda stuff before, it'll take a bit of time (the first time I did this kinda stuff, it took hours to get it right :|.. now it comes slightly easier). Also, as I mentioned, you can write a helper method to do this re-writing for you (so you don't directly need to use the Expression.Whatever methods), but I haven't seen any examples and haven't really needed it yet.
Check out my answer to "switch statement in linq" and see if that points you in the right direction...
The technique i demonstrate there is the one that got me past the scary "no translation to SQL" error.

Categories