I want to get the value from
var guid = Guid.Parse("SOMEGUID-GUID-GUID-GUID-SOMEGUIDGUID"); Expression<Func<Someobject, bool>> selector = x => x.SomeId == guid;
For logging, I need to catch this guid.
I tried the following code, which, in my opinion, is somewhat close to what I'm looking for, but not quite.
BinaryExpression binaryExpression = (BinaryExpression)selector.Body; MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand; ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
Now ConstantExpression provides a 'Value' member that contains what I'm looking for, but I'm a bit puzzled by how to extract it.
And no:
var val = (Guid)constantExpression.Value;
Does not work:)
solvable
The end result is as follows:
BinaryExpression binaryExpression = (BinaryExpression)selector.Body; MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand; var myGuid = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
Subsequent
I did some speed tests using the following code:
static void Main(string[] args) { var id = Guid.Parse("bleh"); Expression<Func<Thingemebob, bool>> selector = x => x.Id == id; var tickList = new List<long>(); for (int i = 0; i < 100000; i++) { var sw = Stopwatch.StartNew(); GetValueWithExpressionsAndReflection(selector); sw.Stop(); tickList.Add(sw.ElapsedTicks); } Trace.WriteLine("GetValueWithExpressionsAndReflection: Average over 100000, first call included: " + tickList.Average()); Trace.WriteLine("GetValueWithExpressionsAndReflection: First call: " + tickList[0]); Trace.WriteLine("GetValueWithExpressionsAndReflection: Average over 100000, first call excluded: " + tickList.Skip(1).Average()); tickList = new List<long>(); for (int i = 0; i < 100000; i++) { var sw = Stopwatch.StartNew(); GetValueWithCompiledExpression(selector); sw.Stop(); tickList.Add(sw.ElapsedTicks); } Trace.WriteLine("GetValueWithCompiledExpression: Average over 100000, first call included: " + tickList.Average()); Trace.WriteLine("GetValueWithCompiledExpression: First call: " + tickList[0]); Trace.WriteLine("GetValueWithCompiledExpression: Average over 100000, first call excluded: " + tickList.Skip(1).Average()); Debugger.Break(); } private static void GetValueWithCompiledExpression(Expression<Func<Note, bool>> selector) { BinaryExpression binaryExpression = (BinaryExpression)selector.Body; MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand; var o = Expression.Lambda(memberExpression).Compile().DynamicInvoke(); } private static void GetValueWithExpressionsAndReflection(Expression<Func<Note, bool>> selector) { BinaryExpression binaryExpression = (BinaryExpression)selector.Body; MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand; ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression; FieldInfo member = (FieldInfo)memberExpression.Member; var instance = constantExpression.Value; var guid = member.GetValue(instance); }
Turns off the MUCH compilation version more slowly. We look at the huge difference. (Dates in ticks):
GetValueWithExpressionsAndReflection: more than 100,000 on average, first call on: 0.93122
GetValueWithExpressionsAndReflection: First call: 851
GetValueWithExpressionsAndReflection: more than 100,000 on average, first call excluded: 0.922719227192272
Versus:
GetValueWithCompiledExpression: On average, more than 100,000, first call on: 499.53669
GetValueWithCompiledExpression: First call: 16818
GetValueWithCompiledExpression: on average more than 100,000, first call excluded: 499,373503735037
Trial tests or not: no doubt, I will use the reflection version. My results seem to be consistent with: http://www.minddriven.de/index.php/technology/dot-net/c-sharp/efficient-expression-values