C# 创建访问属性的表达式

C# 创建访问属性的表达式,c#,lambda,expression,C#,Lambda,Expression,我有以下课程: internal class Sensors { public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>(); } internal class JsonSensor<TType> : IJsonSensor { public TType Value { get; set; } } 内部类传感器 { public JsonSen

我有以下课程:

internal class Sensors
{
    public JsonSensor<double> IOPcwFlSpr { get; set; } = new JsonSensor<double>();
 }

internal class JsonSensor<TType> : IJsonSensor
{
    public TType Value { get; set; }
}
内部类传感器
{
public JsonSensor IOPcwFlSpr{get;set;}=new JsonSensor();
}
内部类JsonSensor:IJsonSensor
{
公共TType值{get;set;}
}
我想构建一个检索该属性的表达式

private static readonly List < PropertyInfo > Properties;

static SensorFactory() {
    Properties = typeof(Json.Sensors).GetProperties().ToList();
}

public void Test(Json.Sensors jsonUpdate) {
    foreach(var property in Properties) {
        var getterMethodInfo = property.GetGetMethod();
        var parameterExpression = Expression.Parameter(jsonUpdate.GetType(), "x");
        var callExpression = Expression.Call(parameterExpression, getterMethodInfo);

        var lambda = Expression.Lambda < Func < JsonSensor < double >>> (callExpression);
        var r = lambda.Compile().Invoke();
    }
}
私有静态只读列表属性;
静态传感器工厂(){
Properties=typeof(Json.Sensors).GetProperties().ToList();
}
公共无效测试(Json.jsonUpdate){
foreach(属性中的var属性){
var getterMethodInfo=property.getMethod();
var parameterExpression=Expression.Parameter(jsonUpdate.GetType(),“x”);
var callExpression=Expression.Call(parameterExpression,getterMethodInfo);
var lambda=Expression.lambda>(调用表达式);
var r=lambda.Compile().Invoke();
}
}
这引发了:

System.InvalidOperationException:类型为“传感器”的变量“x” 从作用域“”引用,但未定义它


这是有道理的,因为我从来没有给“x”分配过实际的对象。如何添加“参数对象”

像这样使用表达式树的关键是使用参数(
ParameterExpression
)编译一次,创建一个
Func
,它接受您的输入(
Foo
)并返回您想要的任何内容(
Bar
)。然后对不同的对象多次重用已编译的委托

我看不出你到底想做什么,但我猜可能是这样的:

使用系统;
使用System.Collections.Generic;
使用System.Linq.Expressions;
运用系统反思;
名称空间Json
{
静态P类
{
静态void Main()
{
var obj=新传感器{IOPcwFlSpr={Value=42.5},无论什么={Value=9};
foreach(SomeUtil.GetSensors(obj)中的var对)
{
Console.WriteLine($“{pair.Name}:{pair.Value}”);
}
}
}
公共级传感器
{
public JsonSensor IOPcwFlSpr{get;set;}=new JsonSensor();
public JsonSensor which{get;set;}=new JsonSensor();
}
公共接口传感器
{
公共字符串值{get;}
}
公共类JsonSensor:IJsonSensor
{
公共TType值{get;set;}
字符串IJsonSensor.Value=>Convert.ToString(值);
}
公共静态类SomeUtil
{
私有静态只读(字符串名称,Func访问器)[]s\u访问器
=Array.ConvertAll(
typeof(Sensors).GetProperties(BindingFlags.Instance | BindingFlags.Public),
prop=>(prop.Name,Compile(prop));
公共静态IEnumerable GetSensors(传感器obj)
{
foreach(s_存取器中的var acc)
收益率返回(acc.name,acc.accessor(obj.Value));
}
私有静态Func编译(PropertyInfo属性)
{
var parameterExpression=Expression.Parameter(typeof(Json.Sensors),“x”);
表达式体=Expression.Property(parameterExpression,Property);
body=表达式.Convert(body,typeof(IJsonSensor));
var lambda=Expression.lambda(主体,参数Expression);
返回lambda.Compile();
}
}
}

是否希望它成为一个参数?或者你希望它是一个常数?注意:如果你只打算编译并使用一次表达式,那么创建一个表达式就没有意义了——你最好只使用反射;在这里使用表达式有什么原因吗?你打算以后缓存它们吗?因为如果你要缓存它们:输入是一个后退一步的参数是有意义的;忘记这里的实际代码;你在这里真正想要实现的是什么?如果只是“更快地访问属性”-也许像FastMember这样的东西可能是一个更简单的选项?附加说明:值是否总是
JsonSensor
?或者可能是
JsonSensor
等?这有点变化things@MarcGravell,也许我做错了。我有一个拥有100多个属性的类(通过json反序列化)。每个属性表示机器中的一个传感器。每次收到新的更新,我都想更新我自己的[b]传感器对象列表[/b]中的新传感器值。因此,我认为最好使用反射来获取“具有100+传感器属性的json类”的所有属性,并使用表达式解析该属性是的,JsonSensor是通用的。double/int/boolOne单词:令人印象深刻。现在我也知道你以前有几个问题。我做错了。我正在存储表达式,而我应该存储func。这两种方法
GetSensors
Compile
准确地解释了我的错误方向。我会把你的答案读几遍,然后开始修改我的代码。PS:我知道我们不应该说谢谢。但我已经在谷歌上搜索(错误的问题)好几个小时了,一无所获。非常感谢你让我走上正轨@在评论中说“谢谢”是可以的!我想这方面的指导就是围绕着问题中的先发制人的生活故事和赠予嘿,马克,如果可以的话,再问一个问题。我以为你犯了一个错误(愚蠢的我;-))。我希望Func的定义是Func。因此,我期望
Lambda(…)
你能解释一下为什么
Sensors
类型的参数被声明为结果参数,而实际上它是函数的参数吗?当然,它工作得很好,我就是不明白why@bas那是因为它是
Func
,而不是
Func