I'm a newbie when it comes to expression trees, so I'm not sure how to ask this question or what terminology to use. Here's an overly-simplifed version of what I'm trying to do:
Bar bar = new Bar();
Zap(() => bar.Foo);
public static void Zap<T>(Expression<Func<T>> source)
{
// HELP HERE:
// I want to get the bar instance and call bar.Zim() or some other method.
}
How can I get to bar inside the Zap method?
Since the expression passed into your Zap method is a tree, you just need to walk the tree using an Expression Tree Visitor and look for the first ConstantExpression in the expression. It will likely be in the following sequence:
(((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value
Note that the bar instance is captured by a closure, which is implemented as an internal class with the instance as a member, which is where the 2nd MemberExpression comes from.
EDIT
Then you have to get the field from the generated closure like so:
static void Main(string[] args)
{
var bar = new Bar();
bar.Foo = "Hello, Zap";
Zap(() => bar.Foo);
}
private class Bar
{
public String Foo { get; set; }
}
public static void Zap<T>(Expression<Func<T>> source)
{
var param = (((source.Body as MemberExpression).Expression as MemberExpression).Expression as ConstantExpression).Value;
var type = param.GetType();
// Note that the C# compiler creates the field of the closure class
// with the name of local variable that was captured in Main()
var field = type.GetField("bar");
var bar = field.GetValue(param) as Bar;
Debug.Assert(bar != null);
Console.WriteLine(bar.Foo);
}
If you know the type of "bar", you can do this (I'm reusing some bits from the codekaizen's answer here):
static void Main(string[] args)
{
var bar = new Bar();
bar.Foo = "Hello, Zap";
Zap(() => bar.Foo);
Console.ReadLine();
}
private class Bar
{
public String Foo { get; set; }
}
public static void Zap<T>(Expression<Func<T>> source)
{
var body = source.Body as MemberExpression;
Bar test = Expression.Lambda<Func<Bar>>(body.Expression).Compile()();
Console.WriteLine(test.Foo);
}
In most cases, you can find an expression representing your object within an expression tree, and then compile and execute this expression and get the object (but this is not a very fast operation, by the way). So, the bit you were missing is the Compile() method. You can find a little bit more info here: How to: Execute Expression Trees.
In this code, I assume that you always pass an expression like "() => object.Member". For a real-world scenario you will need either to analyze that you have an expression you need (e.g. just throw an exception if it's not a MemberExpression). Or use ExpressionVisitor, which is kind of tricky.
I have recently answered a very similar question here:
How do I subscribe to an event of an object inside an expression tree?
Standing on the shoulders of giants above, my final extension method to extract the instance of the class that represented the source of the expression looks as follows:
public static TIn GetSource<TIn, TOut>(this Expression<Func<TIn, TOut>> property)
where TIn: class
{
MemberExpression memberExpression = (MemberExpression)property.Body;
TIn instance = Expression.Lambda<Func<TIn>>(memberExpression.Expression).Compile()();
return instance;
}
I built on all of the answers above, thanks to all.
Related
Given the following class:
public class Foo {
public string Bar {get; set;}
Func<string> GetFunc = () => Bar;
}
the following code will print True:
var foo = new Foo();
var fn = foo.GetFunc;
Console.WriteLine(fn.Target == foo);
because the target of the action delegate is the instance of the object.
How can I get a hold of an expression that represents the target of a LambdaExpression returned by an instance?
public class Foo1 {
public string Bar {get;set;}
Expression<Func<string>> GetExpression = () => Bar;
}
var foo = new Foo();
var expr = foo.GetExpression;
// ???
I thought compiling expr and checking the Target property of the generated delegate would work, and it does return an instance of Closure, where foo is one of the objects referred to by the array at the Constants property.
var closure = expr.Compile().Target as System.Runtime.CompilerServices.Closure;
Console.WriteLine(closure.Constants.Contains(foo));
// prints True
However, this doesn't help me, because if I construct the expression using the factory methods at System.Linq.Expressions.Expression, and specify an external instance as a Constant within the expression tree:
// using static System.Linq.Expressions.Expression;
var foo = new Foo();
Expression<Func<string>> expr = Lambda<Func<string>>(
MakeMemberAccess(
Constant(foo),
typeof(Foo).GetMember("Bar").Single()
)
);
the external instance (foo in this case) will also be included in the Constants.
I am looking specifically for the object (or objects) referred to by this in a compiler-generated LambdaExpression (and if there are no conflicts with other identifiers, the this can be elided).
(Some background can be found here.)
I am trying to achieve the following:
this.helper.Verify(i => i.SomeModule.SomeMethod);
Where:
i is a known type.
SomeModule is a public property of this type.
SomeMethod is the name of the method (passed as delegate I assume).
I would like to be able to avoid specifying the generic types in the Verify method.
Thats how far I've been able to go:
public void Verify<TProp, TResult>(
Expression<Func<KnownType, TProp>> moduleExpression,
Expression<Func<TProp, TResult>> methodExpression)
{
var moduleIdentifier = (moduleExpression.Body as MemberExpression).Member.Name;
var methodIdentifier = (methodExpression.Body as MethodCallExpression).Method.Name;
this.Verify(moduleIdentifier, methodIdentifier, state);
}
But this forces me to write the argument values for the methodExpression, like:
this.helper.Verify(
i => i.SomeModule,
m => m.SomeMethod(arg1, arg2));
Is there a way to achieve what I am looking for?
Finally I end up with a solution that requires delegates.
I need to analyze an expression that can have multiple arguments, like:
i => i.Car.Engine.Intake.Open()
I will extract the last two arguments as a "module" and "method":
public class ExpressionTools
{
public string GetLastInstanceName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (MemberExpression)methodCallExpression.Arguments.Reverse().Skip(1).First();
var instanceName = methodInfoExpression.Member.Name;
return instanceName;
}
public string GetMethodName<TProp, TDelegate>(Expression<Func<TProp, TDelegate>> expression)
{
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
return methodInfo.Name;
}
}
Solution with delegates
A class with generics can be reused since the delegates are not necessary to analyze the expression:
public class Verifier
{
public void Verify<TDelegate>(Expression<Func<KnownType, TDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var moduleName = tools.GetLastInstanceName(methodExpression);
var methodName = tools.GetMethodName(methodExpression);
// My logic.
}
}
Now I need to create the delegates, For that I created a file and declared them without a class:
namespace Whatever
{
public delegate void VoidDelegate();
public delegate void VoidBoolDelegate(bool value);
// etc...
}
Finally, I need to maintain a class that has the same method overloaded with the different delegates.
public class FakeExtensions
{
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
public static void Verify(
this Fake fake,
Expression<Func<KnownType, VoidBoolDelegate>> methodExpression)
{
var tools = new ExpressionTools();
var facilitator = new Verifier(fake, tools);
facilitator.Verify(methodExpression);
}
}
Alternative solution without delegates
The easiest solution would be to pass a default value for each parameter, but that would express that the values are also verified, which is not the case. I really dislike the idea of having something like this:
this.helper.Verify(i => i.SomeModule.SomeMethod(0, false, 0.0, null);
Since Moq is part of our testing framework, it is possible to use It.IsAny as a value for each parameter of a method call, wich expresses that the values don't matter:
this.helper.Verify(i => i.SomeModule.SomeMethod(It.IsAny<int>, It.IsAny<bool>, It.IsAny<double>, It.IsAny<SomeType>);
Why did I choose the delegates solution
I have to verify some calls on a low-level 3rd party API that has methods with up to 100 parameters. I think that the burden of maintaining a delegates list and method overloads pays off in maintainability, readability and ease of use.
I've ended up with a situation where an function expression tree Expression<Func<TClass, TProperty>> is assigned to a global variable of type object and then later in the code I need to call a different method with the expression. I can't change the global objects type; it has to be object.
The code won't compile when trying to call the second method with the global object unless I cast the object as Expression<Func<TClass, TProperty>>. The problem is I don't know what TProperty is at the point that the second method is called.
I've created a quick demo app to illustrate the point (c# console app written in VS2010) - the real application looks nothing like this.
using System;
using System.Linq.Expressions;
namespace FuncExpressionTree
{
public class ViewModel
{
public string StringProperty { get; set; }
public int IntProperty { get; set; }
}
public class Helper<T>
where T : ViewModel
{
private object _global;
public void Execute()
{
AssignToGlobal((T vm) => vm.StringProperty);
ProcessGlobal();
AssignToGlobal((T vm) => vm.IntProperty);
ProcessGlobal();
}
public void AssignToGlobal<TClass, TProperty>(Expression<Func<TClass, TProperty>> expression)
{
_global = expression;
}
public void ProcessGlobal()
{
// invalid cast exception thrown when IntProperty is assigned to _global
AssignToGlobal((Expression<Func<T, string>>)_global);
}
}
class Program
{
static void Main(string[] args)
{
(new Helper<ViewModel>()).Execute();
}
}
}
If we focus on the Execute() method.
First global is assigned expression for the string property.
ProcessGlobal executes and works because I'm casting to Expression<Func<T, string>>.
Next global is assigned expression for int property.
ProcessGlobal again executes but its at this point that an invalid cast exception is thrown. It would work if I changed it to cast Expression<Func<T, int>> instead but then the string property wouldn't work. Also Expression<Func<T, object>> throws an invalid cast exception.
I feel like Im missing something and that it should be possible to do something with the System.Linq.Expressions namespace to dynamically invoke the the second method (eg AssignToGlobal within ProcessGlobal in the above example).
So how can I get this to work in a generic way?
public void ProcessGlobal()
{
var globalType = _global.GetType(); // globalType = Expression<Func<TClass, TProperty>>
var functionType = globalType.GetGenericArguments()[0]; // functionType = Func<TClass, TProperty>
var functionGenericArguments = functionType.GetGenericArguments(); // v = [TClass, TProperty]
var method = this.GetType().GetMethod("AssignToGlobal").MakeGenericMethod(functionGenericArguments); //functionGenericArguments = AssignToGlobal<TClass, TProperty>
method.Invoke(this, new[] { this._global }); // Call AssignToGlobal<TClass, TProperty>)(this._global);
}
I am looking for a way to combine two lambda expressions, without using an Expression.Invoke on either expression. I want to essentially build a new expression that chains two separate ones. Consider the following code:
class Model {
public SubModel SubModel { get; set;}
}
class SubModel {
public Foo Foo { get; set; }
}
class Foo {
public Bar Bar { get; set; }
}
class Bar {
public string Value { get; set; }
}
And lets say I had two expressions:
Expression<Func<Model, Foo>> expression1 = m => m.SubModel.Foo;
Expression<Func<Foo, string>> expression2 = f => f.Bar.Value;
And I want to join them together to functionally get the following expression:
Expression<Func<Model, string>> joinedExpression = m => m.SubModel.Foo.Bar.Value;
The only way I could think to do this is to use a ExpressionVisitor like this:
public class ExpressionExtender<TModel, TIntermediate> : ExpressionVisitor
{
private readonly Expression<Func<TModel, TIntermediate>> _baseExpression;
public ExpressionExtender(Expression<Func<TModel, TIntermediate>> baseExpression)
{
_baseExpression = baseExpression;
}
protected override Expression VisitMember(MemberExpression node)
{
_memberNodes.Push(node.Member.Name);
return base.VisitMember(node);
}
private Stack<string> _memberNodes;
public Expression<Func<TModel, T>> Extend<T>(Expression<Func<TIntermediate, T>> extend)
{
_memberNodes = new Stack<string>();
base.Visit(extend);
var propertyExpression = _memberNodes.Aggregate(_baseExpression.Body, Expression.Property);
return Expression.Lambda<Func<TModel, T>>(propertyExpression, _baseExpression.Parameters);
}
}
And then its used like this:
var expExt = new ExpressionExtender<Model, Foo>(expression1);
var joinedExpression = expExt.Extend(expression2);
It works, but it feels a bit clunky to me. I'm still trying to wrap my head expressions and wondering if there is a more idiomatic way to express this, and I have the sneaky suspicion that I missing something obvious.
The reason I want to do this is to use it with the ASP.net mvc 3 Html helpers. I have some deeply nested ViewModels and some HtmlHelper extensions that help deal with those, so the expression needs to be just a collection of MemberExpressions for the built in MVC helpers to process them correctly and build the correctly deeply nested name attribute values. My first instinct was to use Expression.Invoke() and invoke the first expression and chain it to the second, but the MVC helpers didn't like that very much. It lost its hierarchical context.
Use a visitor to swap all instances of the parameter f to m.SubModel.Foo, and create a new expression with m as the parameter:
internal static class Program
{
static void Main()
{
Expression<Func<Model, Foo>> expression1 = m => m.SubModel.Foo;
Expression<Func<Foo, string>> expression2 = f => f.Bar.Value;
var swap = new SwapVisitor(expression2.Parameters[0], expression1.Body);
var lambda = Expression.Lambda<Func<Model, string>>(
swap.Visit(expression2.Body), expression1.Parameters);
// test it worked
var func = lambda.Compile();
Model test = new Model {SubModel = new SubModel {Foo = new Foo {
Bar = new Bar { Value = "abc"}}}};
Console.WriteLine(func(test)); // "abc"
}
}
class SwapVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public SwapVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
Your solution seems to be narrowly tailored to your specific problem, which seems inflexible.
It seems to me that you could solve your problem straightforwardly enough through simple lambda substitution: replace instances of the parameter (or "free variable" as they call it in lambda calculus) with the body. (See Marc's answer for some code to do so.)
Since parameter in expression trees have referential identity rather than value identity there isn't even a need to alpha rename them.
That is, you have:
Expression<Func<A, B>> ab = a => f(a); // could be *any* expression using a
Expression<Func<B, C>> bc = b => g(b); // could be *any* expression using b
and you wish to produce the composition
Expression<Func<A, C>> ac = a => g(f(a)); // replace all b with f(a).
So take the body g(b), do a search-and-replace visitor looking for the ParameterExpression for b, and replace it with the body f(a) to give you the new body g(f(a)). Then make a new lambda with the parameter a that has that body.
Update: the below answer generates an "Invoke" which EF does not support.
I know this is an old thread, but I have the same need and I figured out a cleaner way to do it. Assuming that you can alter your "expression2" to user a generic lambda, you can inject one like this:
class Program
{
private static Expression<Func<T, string>> GetValueFromFoo<T>(Func<T, Foo> getFoo)
{
return t => getFoo(t).Bar.Value;
}
static void Main()
{
Expression<Func<Model, string>> getValueFromBar = GetValueFromFoo<Model>(m => m.SubModel.Foo);
// test it worked
var func = getValueFromBar.Compile();
Model test = new Model
{
SubModel = new SubModel
{
Foo = new Foo
{
Bar = new Bar { Value = "abc" }
}
}
};
Console.WriteLine(func(test)); // "abc"
}
}
I am trying to use Lambda Expressions in a project to map to a third party query API. So, I'm parsing the Expression tree by hand.
If I pass in a lambda expression like:
p => p.Title == "title"
everything works.
However, if my lambda expression looks like:
p => p.Title == myaspdropdown.SelectedValue
Using the .NET debugger, I don't see the actual value of that funciton. Instead I see something like:
p => p.Title = (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue)
What gives? And when I try to grab the right side of the expression as a string, I get (value(ASP.usercontrols_myaspusercontrol_ascx).myaspdropdown.SelectedValue) instead of the actual value. How do I get the actual value?
Remember that when you're dealing with the lambda expression as an expression tree, you don't have executable code. Rather you have a tree of expression elements, that make up the expression you wrote.
Charlie Calvert has a good post that discusses this in detail. Included is an example of using an expression visualiser for debugging expressions.
In your case, to get the value of the righthand side of the equality expression, you'll need to create a new lambda expression, compile it and then invoke it.
I've hacked together a quick example of this - hope it delivers what you need.
public class Class1
{
public string Selection { get; set; }
public void Sample()
{
Selection = "Example";
Example<Book, bool>(p => p.Title == Selection);
}
public void Example<T,TResult>(Expression<Func<T,TResult>> exp)
{
BinaryExpression equality = (BinaryExpression)exp.Body;
Debug.Assert(equality.NodeType == ExpressionType.Equal);
// Note that you need to know the type of the rhs of the equality
var accessorExpression = Expression.Lambda<Func<string>>(equality.Right);
Func<string> accessor = accessorExpression.Compile();
var value = accessor();
Debug.Assert(value == Selection);
}
}
public class Book
{
public string Title { get; set; }
}
To get the actual value, you need to apply the logic of the expression tree to whatever context you've got.
The whole point of expression trees is that they represent the logic as data rather than evaluating the expression. You'll need to work out what the lambda expression truly means. That may mean evaluating some parts of it against local data - you'll need to decide that for yourself. Expression trees are very powerful, but it's not a simple matter to parse and use them. (Ask anyone who's written a LINQ provider... Frans Bouma has bemoaned the difficulties several times.)
Just been struggling with exactly the same issue, thanks Bevan. On an extension, the following is a generic pattern you can use to extract the value (using this in my query engine).
[TestFixture]
public class TestClass
{
[Test]
public void TEst()
{
var user = new User {Id = 123};
var idToSearch = user.Id;
var query = Creator.CreateQuery<User>()
.Where(x => x.Id == idToSearch);
}
}
public class Query<T>
{
public Query<T> Where(Expression<Func<T, object>> filter)
{
var rightValue = GenericHelper.GetVariableValue(((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right.Type, ((BinaryExpression)((UnaryExpression)filter.Body).Operand).Right);
Console.WriteLine(rightValue);
return this;
}
}
internal class GenericHelper
{
internal static object GetVariableValue(Type variableType, Expression expression)
{
var targetMethodInfo = typeof(InvokeGeneric).GetMethod("GetVariableValue");
var genericTargetCall = targetMethodInfo.MakeGenericMethod(variableType);
return genericTargetCall.Invoke(new InvokeGeneric(), new[] { expression });
}
}
internal class InvokeGeneric
{
public T GetVariableValue<T>(Expression expression) where T : class
{
var accessorExpression = Expression.Lambda<Func<T>>(expression);
var accessor = accessorExpression.Compile();
return accessor();
}
}
I'm not sure I understand. Where are you "seeing" that? Is that at design-time or run-time? Lambda expressions can be thought of essentially as anonymous delegates, and will operate with deferred execution. So you shouldn't expect to see the value assigned until after execution has passed that line, obviously.
I don't think that's really what you mean though... if you clarify the question a bit maybe I can help :)