- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
selector = x => -6ren">
我正在寻找一个值
var guid = Guid.Parse("SOMEGUID-GUID-GUID-GUID-SOMEGUIDGUID");
Expression<Func<Someobject, bool>> selector = x => x.SomeId == guid;
出于日志记录的目的,我需要能够找出该 guid。
我尝试了以下代码,我觉得它有点接近我正在寻找的东西,但又不完全是。
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
ConstantExpression constantExpression = (ConstantExpression)memberExpression.Expression;
现在,ConstantExpression 公开了一个成员“Value”,它确实包含我正在寻找的内容,但我有点困惑如何实际提取它。
没有:
var val = (Guid)constantExpression.Value;
不起作用:)
已解决
最终结果如下:
BinaryExpression binaryExpression = (BinaryExpression)selector.Body;
MemberExpression memberExpression = (MemberExpression)((UnaryExpression)binaryExpression.Right).Operand;
var myGuid = Expression.Lambda(memberExpression).Compile().DynamicInvoke();
跟进
我使用以下代码进行了一些粗鲁的速度测试:
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);
}
事实证明编译版本要慢得多。我们正在寻找一个巨大的差异。 (时间以滴答为单位):
GetValueWithExpressionsAndReflection: Average over 100000, first call included: 0,93122
GetValueWithExpressionsAndReflection: First call: 851
GetValueWithExpressionsAndReflection: Average over 100000, first call excluded: 0,922719227192272
对比:
GetValueWithCompiledExpression: Average over 100000, first call included: 499,53669
GetValueWithCompiledExpression: First call: 16818
GetValueWithCompiledExpression: Average over 100000, first call excluded: 499,373503735037
是否进行基本测试:毫无疑问,我将使用反射版本。我的结果似乎与以下内容一致: http://www.minddriven.de/index.php/technology/dot-net/c-sharp/efficient-expression-values
最佳答案
您的 const 表达式的类型为 EFAndExpressions.Program+<>c__DisplayClass0
.这意味着表达式具有以下结构:
var compilerGeneratedClass = new compilerGeneratedClass() {
guid = Guid.Parse("SOMEGUID-GUID-GUID-GUID-SOMEGUIDGUID"); };
Expression<Func<Someobject, bool>> selector = x => x.SomeId == compilerGeneratedClass.guid;
编译器会为你做这件事。使用反编译器查看详细信息。
现在你知道表达式树的样子了,你可以分解它了。您需要使用反射来获取 compilerGeneratedClass.guid
的运行时值字段或属性。
这个值不直接是表达式树的一部分。
关于c# - 从 ConstantExpression 获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32308674/
给定Msdn:常量表达式是可以在编译时完全计算的表达式。 但是在下面的示例代码中,我有一个无法在编译时评估的 contantExpression。 我应该错过一些东西,但是什么? public cla
给定 Msdn:常量表达式是可以在编译时完全求值的表达式。 但是在下面的示例代码中,我有一个无法在编译时求值的 contantExpression。 我应该错过了什么,但是什么? public cla
当 ConstantExpression 值为 null 时,如何确定它的类型?我以前一直使用以下代码检测类型,但是当 ConstantExpression 值为 null 时它会导致 null 异常
我正在寻找一个值 var guid = Guid.Parse("SOMEGUID-GUID-GUID-GUID-SOMEGUIDGUID"); Expression> selector = x =>
我创建了一个覆盖 VisitConstant 的 ExpressionVisitor 实现。但是,当我创建一个使用局部变量的表达式时,我似乎无法获得该变量的实际值。 public class Pers
无论怎么想,我都不是表达式树大师,我拥有的代码如下所示: int external = 10; using(var session = new Session()) {
我尝试实现自己的表达式序列化器/反序列化器,以便通过服务传递它(我想实现我自己的 EF Core 服务端点)。所以,现在我对 LambdaExpressions 中的集合有问题。例如, var dat
我尝试实现自己的表达式序列化器/反序列化器,以便通过服务传递它(我想实现我自己的 EF Core 服务端点)。所以,现在我对 LambdaExpressions 中的集合有问题。例如, var dat
我有一些代码生成表达式作为数据库中读取的“where”语句传递,我正在尝试加快速度。 下面的示例使用 where 语句来匹配具有传入值的表的 PK: private Expression MakeWh
下面是我的问题的简单演示代码。 [TestClass] public class ExpressionTests { [TestMethod] public void TestPara
这个问题在 NHibernate 2 和 3 中都会出现。我有一个类 A,它有一个类 B 的成员集。直接查询类可以很好地执行。但是,当我将涉及类 B 的表达式之一传递到方法中时,出现以下错误: Sys
这个问题在 NHibernate 2 和 3 中都会出现。我有一个类 A,它有一个类 B 的成员集。直接查询类可以很好地执行。但是,当我将涉及类 B 的表达式之一传递到方法中时,出现以下错误: Sys
我是一名优秀的程序员,十分优秀!