Best way to check if value is null in Expression Tree - c#

What is the best way to check if constant is null in Expression Trees?
// Method to call (Regex.IsMatch)
MethodInfo isMatchMethod = typeof(Regex).GetMethod("IsMatch", new[] { typeof(string), typeof(string), typeof(RegexOptions) });
// The member you want to evaluate: (x => x.<property_name>)
var member = Expression.Property(param, propertyName);
// The value you want to evaluate
var constant = Expression.Convert(Expression.Constant(value), type);
// How to check if constant is null???
var expr = Expression.Call(isMatchMethod, member, constant, Expression.Constant(RegexOptions.IgnoreCase));
// Doesn't work
// Expression notNullConstant = value != null ? constant : Expression.Convert(Expression.Constant(string.Empty), type);
//var expr = Expression.Call(isMatchMethod, member, notNullConstant, Expression.Constant(RegexOptions.IgnoreCase));

Not sure what the problem is. You can translate a ?? b literally into a tree with Expression.Coalesce. If in doubt compile an expression with the C# compiler and look at what it did.
http://tryroslyn.azurewebsites.net/#f:r/K4Zwlgdg5gBAygTxAFwKYFsDcAoUlaIoYB0AMpAI7ECiAHgA4BOqI4A9hCDvcAEYA2YAMYwh/AIasYAYRgBvbDCUweA4TABubMABMYAWQAUASnmLlFukxbsIAHgBiwCELspG+AHyeY4mAF4YEwCfACJQmAB+SJhwnAsAX2wEoAA=
Meanwhile you have asked how to compile ?:. The answer is the same: Simply decompile existing code to see what is being output. Use Expression.Condition.

Related

C# Compiled expression to create new instance of T and copy values to its properties from another instance of T

I would like to know if it is possible to create an instance of a type known only at runtime and assign values to the properties of this instance by using compiled expressions and if so how it is to be done.
I have a generic class with a method which accepts an instance of T and returns a copy. T is only known at runtime or rather is user/consumer defined. I know how to do so with reflection (assuming it has an empty constructor in this example and without exception handling or null checks for simplification).
public class MyClass<T>
{
public T CreateCopy(T source)
{
var type = typeof(T);
var copy = type.GetConstructor(Type.EmptyTypes).Invoke(null);
foreach(var pi in type.GetProperties())
{
pi.SetValue(copy, pi.GetValue(source));
}
return copy;
}
}
Reflection is quite expensive and after some digging i found an option to at least create an instance of T with compiled expressions.
var type = typeof(T);
Expression.Lambda<Func<T>>(Expression
.New(type.GetConstructor(Type.EmptyTypes)
?? throw new InvalidOperationException(
$"Type has to have an empty public constructor. {type.Name}")))
.Compile();
After some benchmarking i have found out that it performs around 6 times faster than the CreateCopy(...) method. The thing is that i do not know which type will be passed in as a generic and how many properties it will have.
Is there a way to do all of the operations from CreateCopy(...) method with compiled expressions?
Ihave looked into Expression.Asign, Expression.MemberInit but i am not able to find anything appropriate. The problem with Expression.MemberInit ist that it expects to have an Expresssion.Bind and Expression.Constant but i cant get the values of the properties from the passed instance of T into it. Is there a way?
Thank you.
P.S. So i am looking for something like:
var type = typeof(T);
var propertyInfos = type.GetProperties();
var ctor = Expression.New(type.GetConstructor(Type.EmptyTypes));
var e = Expression.Lambda<Func<T, T>>(Expression
.MemberInit(ctor, propertyInfos.Select(pi =>
Expression.Bind(pi, Expression.Constant(pi.GetValue(source)))))).Compile();
You are almost there. What you need is to define a parameter and then assign the properties with property access expression like below :
public static T Express<T>(T source)
{
var parameter = Expression.Parameter(typeof(T), "source");
var type = typeof(T);
var ctor = Expression
.New(type.GetConstructor(Type.EmptyTypes));
var propertyInfos = type.GetProperties();
var e = Expression
.Lambda<Func<T, T>>(
Expression
.MemberInit(ctor, propertyInfos.Select(pi =>
Expression.Bind(pi, CanBeAssigned(pi.PropertyType)
? (Expression)Expression.Property(parameter, pi.Name)
: Expression.Call(typeof(Program).GetMethod(nameof(Express))
.MakeGenericMethod(pi.PropertyType),
Expression.Property(parameter, pi.Name)
))
)),
parameter
);
var x = e.Compile();
var z = x(source);
return z;
}
public static bool CanBeAssigned(Type t)
{
return t.IsValueType || t.Name == "String"; // this might need some improvements
}

Dynamic expression: How compiler compiles and what lamda expression to expect

I am following this question Returning a nested generic Expression<Func<T, bool>>
And I am interested in how compiler reads and compile it to
for example
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
PropertyInfo pi = typeof(T).GetProperty(prop);
MemberExpression me = Expression.MakeMemberAccess(pe, pi);
ConstantExpression ce = Expression.Constant(val);
BinaryExpression be = Expression.Equal(me, ce);
return Expression.Lambda<Func<T, bool>>(be, pe);
Update Also need explanation of each method
My question is what lamda expression should I expect after it compiles?
See the comments in the code below.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApp5
{
class Program
{
static void Main(string[] args)
{
var myType = new MyType();
myType.p = "Some Value";
var compareMethod = DoWork<MyType>("Some Value", "p");
var isEqual = compareMethod(myType);
}
public static Func<T, bool> DoWork<T>(object val, string prop)
{
//The code below will construct an expression like 'p => p.prop == value'
//Creates the parameter part of an expression. So the 'p =>' part of the expression.
ParameterExpression pe = Expression.Parameter(typeof(T), "p");
//Get access to the property info, like the getter and setter.
PropertyInfo pi = typeof(T).GetProperty(prop);
// // Constructs the part of the expression where the member is referenced, so the 'p.prop' part.
MemberExpression me = Expression.MakeMemberAccess(pe, pi);
//Creates the constant part of the expression, the 'value' part.
ConstantExpression ce = Expression.Constant(val);
//creates the comparison part '==' of the expression.
//So this requires the left and right side of 'left == right'
//Which is the property and the constant value.
//So 'p.prop == value'
BinaryExpression be = Expression.Equal(me, ce);
//Puts the 'p => ' and 'p.prop == value' parts of the expression together to form the
//complete lambda
//Compile it to have an executable method according to the same signature, as
//specified with Func<T, bool>, so you put a class in of type T and
//the 'p.prop == value' is evaluated, and the result is returned.
return Expression.Lambda<Func<T, bool>>(be, pe).Compile();
}
}
public class MyType
{
public string p { get; set; }
}
}
That said, I think it is a complex way of only comparing. The usage case you have in mind may justify it. Are you working with LINQ-to-SQL or so that you have to work with expressions? In most cases from my epxerience, you can solve this with Funcs and interfaces, maybe in combination with a wrapper class in case of 3rd party classes. The code itself probably creates some in memory MSIL, which is then compiled in memory to native code using the Just-In-Time compiler of the CLR, where the allocation of the memory is marked as executable. I do not have detailed knowledge of how that works, this is just a guess. For more information on how memory allocation can be marked for different purposes see Memory Protection Constants.

How do I 'dereference' a closure? [duplicate]

I have built my own SQL Query builder that breaks apart an Expression, however, I'm having an issue trying to get the value of string defined in the same function as the lambda expression.
Here is what I am trying to do in console app:
private static void MyBuilderTest()
{
var sqlBuilder = new SqlBuilder();
// Doesn't work -- NEED GUIDANCE HERE
var testValue = "Test"; // Defined in the same function as the lambda below
sqlBuilder.Select<FooObject>(o => o.FooValue == testValue);
// Works
var someObject = new SomeObject { SomeValue = "classTest };
sqlBuilder.Select<FooObject>(o => o.FooValue == someObject.SomeValue);
}
In my builder it subclasses from ExpressionVisitor, and I override the VisitMember. I found that a string defined in at the base Console level will come back as:
Node.Expression.NodeType == ExpressionType.Constant
The Node.Expression passes back properties of:
CanReduce = false
DebugView = ".Constant<ConsoleApplication1.Program+<>c__DisplayClass1>(ConsoleApplication1.Program+<>c__DisplayClass1)"
NodeType = Constant
Type = System.Type {System.RunetimeType}
Value = {ConsoleApplication1.Program}
The Node.Expression.Value contains:
testValue = "Test" (Type: string)
How do I get this value? I've tried several things, like:
var memberType = node.Expression.Type.DeclaringType;
This passes back a ConsoleApplication1.Program type.
However, when I do:
memberType.GetProperty("testValue"); // Declaring Type from Expression
It passes back null.
The above methods work fine if I place the lambda "strings" in a class, but doesn't work if they string is defined in the console function.
Can anyone tell me how to get the string value if it's defined at the function level of the lambda?
EDITED: Added VisitMember
protected override Expression VisitMember(MemberExpression node)
{
if (node.NodeType == ExpressionType.Constant)
{
// Node.Expression is a ConstantExpression type.
// node.Expression contains properties above
// And Has Value of: {ConsoleApplication1.Program}
// Expanding Value in Watch window shows: testValue = "Test"
// How do I get this value, if the ConsoleApplication1.Program type doesn't
// even know about it? Looks like maybe a dynamic property?
}
}
EDITED
Added code to the console app example to show what works and what doesn't.
The lambda in your example has "closed over" the testValue variable, meaning the compiler has captured it as a field of the same name in an automatically generated class called ConsoleApplication1.Program+<>c__DisplayClass1>. You can use normal reflection to get the current value of that field by casting the right hand-side of the binary expression into a MemberExpression.
var testValue = "hello";
var expr = (Expression<Func<string, bool>>) (x => x == testValue);
var rhs = (MemberExpression) ((BinaryExpression) expr.Body).Right;
var obj = ((ConstantExpression) rhs.Expression).Value;
var field = (FieldInfo) rhs.Member;
var value = field.GetValue(obj);
Debug.Assert(Equals(value, "hello"));
testValue = "changed";
value = field.GetValue(obj);
Debug.Assert(Equals(value, "changed"));
Alternatively you can change your variable into a constant.
const string testValue = "hello";
var expr = (Expression<Func<string, bool>>) (x => x == testValue);
var value = ((ConstantExpression) ((BinaryExpression) expr.Body).Right).Value;
Debug.Assert(Equals(value, "hello"));
Instead of doing this by yourself, have a look at PartialEvaluator from Matt Warren. It replaces all references to constants with the constants themselves.

Is reflection used when retrieving information from a linq expression?

I have the following extension method:
public static string ToPropertyName<T,E>(this Expression<Func<E, T>> propertyExpression)
{
if (propertyExpression == null)
return null;
string propName;
MemberExpression propRef = (propertyExpression.Body as MemberExpression);
UnaryExpression propVal = null;
// -- handle ref types
if (propRef != null)
propName = propRef.Member.Name;
else
{
// -- handle value types
propVal = propertyExpression.Body as UnaryExpression;
if (propVal == null)
throw new ArgumentException("The property parameter does not point to a property", "property");
propName = ((MemberExpression)propVal.Operand).Member.Name;
}
return propName;
}
I use linq expression when passing property names instead of strings to provide strong typing and I use this function to retrieving the name of the property as a string. Does this method use reflection?
My reason for asking is this method is used quite a lot in our code and I want it to be reasonably fast enough.
As far as I know, reflection is not involved in the sense that some kind of dynamic type introspection happens behind the scenes. However, types from the System.Reflection such as Type or PropertyInfo are used together with types from the System.Linq.Expressions namespace. They are used by the compiler only to describe any Func<T,E> passed to your method as an abstract syntax tree (AST). Since this transformation from a Func<T,E> to an expression tree is done by the compiler, and not at run-time, only the lambda's static aspects are described.
Remember though that building this expression tree (complex object graph) from a lambda at run-time might take somewhat longer than simply passing a property name string (single object), simply because more objects need to be instantiated (the number depends on the complexity of the lambda passed to your method), but again, no dynamic type inspection à la someObject.GetType() is involved.
Example:
This MSDN article shows that the following lambda expression:
Expression<Func<int, bool>> lambda1 = num => num < 5;
is transformed to something like this by the compiler:
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");
ConstantExpression five = Expression.Constant(5, typeof(int));
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);
Expression<Func<int, bool>> lambda1 =
Expression.Lambda<Func<int, bool>>(
numLessThanFive,
new ParameterExpression[] { numParam });
Beyond this, nothing else happens. So this is the object graph that might then be passed into your method.
Since you're method naming is ToPropertyName, I suppose you're trying to get the typed name of some particular property of a class. Did you benchmark the Expression<Func<E, T>> approach? The cost of creating the expression is quite larger and since your method is static, I see you're not caching the member expression as well. In other words even if the expression approach doesn't use reflection the cost can be high. See this question: How do you get a C# property name as a string with reflection? where you have another approach:
public static string GetName<T>(this T item) where T : class
{
if (item == null)
return string.Empty;
return typeof(T).GetProperties()[0].Name;
}
You can use it to get name of property or a variable, like this:
new { property }.GetName();
To speed up further, you would need to cache the member info. If what you have is absolutely Func<E, T> then your approach suits. Also see this: lambda expression based reflection vs normal reflection
A related question: Get all the property names and corresponding values into a dictionary

Expression.LessThan vs LambdaExpression<Func<ParamType,object>>

I've got a LambdaExpression which takes one object as a Parameter and ultimately returns an object.
For the purposes of testing, here's a Lambda (created longhand to match what i'm really passing in) that returns a DateTime boxed as an object.
For the purposes of working this through, the LambdaExpression takes an XmlNode and returns an object.
It must return an object, the real return type could be any of: DateTime,bool,int,decimal,XmlDocument [so far]
The general idea is that somewhere deep in a parser, this lambda is created and it extracts a value from it's input parameter and returns it typed, but boxed in an object.
XmlNode node = null;
ParameterExpression instanceExpression = Expression.Parameter(typeof(DynamicNode), "instance");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
BlockExpression block = Expression.Block(
typeof(object),
new[] { result },
Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))),
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))));
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression);
Later in the code, we're evaluating <, <=, >, >=, == and != so we want to compare the result of this LambdaExpression to another Expression
Usually, we can assume the LambdaExpression is on the left of the Expression.LessThan
on the right, could be pretty much any expression, but lets assume it's typed.
That means that it could be ConstantExpression or similar... but it has a type.
This means that Expression.LessThan [for example] fails because the LambdaExpression when Expression.Invoke is called on it returns an object and the RHS is whatever that type is.
Assuming that the type boxed inside the object returned from the LambdaExpression is actually comparable to the type on the right hand side; e.g.
(object)5 < 6
How do I write an expression that can compare the boxed type to the unboxed type without crashing?
I've tried various permutations in linqpad, including trying to write this in normal c#- i.e. no Expressions, just nested if-then-else however I couldn't get that working quite right.
Normally, i'd probably write something like this:
/*
int i = 3;
object o = (object)i;
int compare = 4;
*/
DateTime dt = DateTime.Now;
object o = (object)dt;
DateTime compare = DateTime.Now.AddSeconds(1);
bool b = false;
if(o.GetType().IsAssignableFrom(compare.GetType()))
{
if(o is int)
{
b = (int)o < (int)(object)compare;
}
if(o is DateTime)
{
b = (DateTime)o < (DateTime)(object)compare;
}
if(o is decimal)
{
b = (decimal)o < (decimal)(object)compare;
}
}
Console.WriteLine(b);
With this, assuming o and compare are actually the same type and one of them is boxed as an object, we can still perform the < operation...
So I guess my question is, how do I write the above code when I have a LambdaExpression on the left, and Expression on the right [if the two are not the same type, false as a result is better than a crash]
Hope someone can help,
Gareth
How do I write an expression that can
compare the boxed type to the unboxed
type without crashing?
You can use the Expression.Unbox method for this: "Creates a UnaryExpression that represents an explicit unboxing."
Let's take your (int)(object)5 < 6 example:
// boxed int
var left = Expression.Constant(5, typeof(object));
// int
var right = Expression.Constant(6, typeof(int));
// More generally, you can use right.Type instead of typeof(int)
// if its static type is appropriate.
// Otherwise, you may need to unbox it too.
var unboxedLeft = Expression.Unbox(left, typeof(int));
var lessThanEx = Expression.LessThan(unboxedLeft, right);
var expression = Expression.Lambda<Func<bool>>(lessThanEx, null);
// True : (int)(object)5 < 6
bool b = expression.Compile()();
So I guess my question is, how do I
write the above code when I have a
LambdaExpression on the left, and
Expression on the right. [if the two are not the same type, false as a result is better > than a crash]
In this case, you can write a conditional-expression that checks if the run-time type of the boxed-object is the same as the type of the right-hand side, and do the unboxing + less-than comparison if they are, or just return false otherwise.
E.g.
// From earlier
var left = ...
var right = ...
var lessThanEx = ...
var body = Expression.Condition(Expression.TypeEqual(left, right.Type),
lessThanEx,
Expression.Constant(false));
var expression = Expression.Lambda<Func<bool>>(body, null);
Combining my original post with your guys answers- this seems to function in LinqPad
XmlNode node = null;
ParameterExpression instanceExpression = Expression.Parameter(typeof(XmlNode), "instance");
ParameterExpression result = Expression.Parameter(typeof(object), "result");
LabelTarget blockReturnLabel = Expression.Label(typeof(object));
BlockExpression block = Expression.Block(
typeof(object),
new[] { result },
//this would normally be a function invoke
Expression.Assign(result, Expression.Convert(Expression.Constant(DateTime.Now.AddSeconds(-1)), typeof(object))),
Expression.Return(blockReturnLabel, result),
Expression.Label(blockReturnLabel, Expression.Constant(-2, typeof(object))));
LambdaExpression lax = Expression.Lambda<Func<XmlNode, object>>(block, instanceExpression);
var left = Expression.Invoke(lax, instanceExpression);
//false result
//var right = Expression.Constant(5, typeof(int));
//true result
var right = Expression.Constant(DateTime.Now, typeof(DateTime));
var unboxedLeft = Expression.Unbox(left, right.Type);
var lessThanEx = Expression.LessThan(unboxedLeft, right);
var body = Expression.Condition(Expression.TypeEqual(left, right.Type), lessThanEx, Expression.Constant(false));
var expression = Expression.Lambda<Func<XmlNode, bool>>(body, instanceExpression);
bool b = expression.Compile()(node);
Console.WriteLine(b);

Categories

Resources