【发布时间】:2014-12-12 08:38:50
【问题描述】:
首先,简要概述一下我正在尝试做的事情:我想要获取一个 C# 表达式,对其进行序列化,将其发送到另一个进程,对其进行反序列化,然后使用它来过滤列表。这是警告 - 创建表达式时,它是针对通用参数类型 T 完成的,但是当它被反序列化时,它需要与动态相反。这样做的原因是,当它最终在不同进程中的服务器上使用时,它将针对动态列表执行此操作,因为在该上下文中我不会有类型信息。
我觉得我已经很接近了,因为我使用了 Newtonsoft.Json 和 Serialize.Linq 库来组合概念证明,但我只能在不使用动态的情况下让它工作(例如,我有可用的类型 T在序列化端(客户端)和反序列化端(服务器)。在一些代码上向你展示我所拥有的......
鉴于此:
public class Person
{
public string Name { get; set; }
public string Email { get; set; }
}
...作为我们正在使用的类型。我有一个有接口的客户端:
public interface IClient
{
T Get<T>(Expression<Func<T, bool>> query);
}
...所以我可以这样做:
var client = new Client();
var john = client.Get<Person>(p => p.Name == "John");
...到目前为止一切都很好。在 client.Get() 方法中,我正在获取传递的表达式并将其序列化并发送到服务器。服务器如下所示:
public dynamic Server(string serializedExpression)
{
var people = new List<dynamic>
{
new { Name = "John", Email = "john@stackoverflow.com" },
new { Name = "Jane", Email = "jane@stackoverflow.com" }
};
var serializer = new ExpressionSerializer(new JsonSerializer());
var deserializedExpression = (Expression<Func<dynamic, bool>>)serializer.DeserializeText(serializedExpression);
return people.FirstOrDefault(deserializedExpression.Compile());
}
...这就是问题发生的地方,因为我试图将其反序列化为一种
Expression<Func<dynamic, bool>>
...而不是...
Expression<Func<Person, bool>>.
所以我的问题是:
1) 我正在尝试做的事情是否可能?似乎使用 ExpressionVisitor 可以更改通用参数类型,我尝试这样做以在序列化和发送之前从 Person 更改为 dynamic,但没有运气。
2) 有没有更好的方法来做我想要完成的事情?我知道第一个问题是我为什么不直接访问服务器上表达式 Func 中指定的类型 T,但由于服务器的性质,这是不可能的。我基本上希望在客户端上使用 Linq 来指定查询谓词,同时针对动态列表执行这些谓词。
提前感谢您提供的任何答案或想法。
问候,
克雷格
【问题讨论】:
-
可能是愚蠢的建议,但是通过拥有一些您知道所有内容都继承自的基本
IMyObject接口或类,是否有可能在服务器上“不太动态”? -
在尝试解决这个问题后的问题。您实际尝试过滤的列表是
dynamics的集合还是静态类型? -
Nate - 不是一个愚蠢的建议,我曾想过这样做,但一旦我用 IMyObject 标记我的表达式,我就失去了在我的表达式中做有意义的 lambda 的能力(AFAIK) ' 将被限制为只对 IMyObject 成员进行操作,除非我做了一堆我想避免的强制转换。
-
我应该指定我实际上是在谈论拥有一个实际的
Person而不是匿名类型 (new {...}) 的集合。列表中的T并不多。 -
Ty - 我想要实际应用表达式的服务器上的列表将是一个动态集合,因为我在该进程上下文中没有任何相关的类型信息。服务器不知道 Person 类型是什么,因为它的数据都是从 JSON 加载到动态中的。问题是服务器上的数据将匹配定义的 Person 类型,因此表达式应该针对这些动态正确操作,因为它们将具有客户端上 Person 类型定义的所有相同属性。这有意义吗?
标签: c# linq expression func