C# lambda表达式内泛型类型的访问属性

C# lambda表达式内泛型类型的访问属性,c#,mongodb,generics,lambda,C#,Mongodb,Generics,Lambda,标题可能模棱两可,但让我解释一下 我正在使用MongoDb和MongoDb的c#驱动程序,我们可以创建一个FilterDefinition来创建一个过滤器来获取数据,如下所示: var Filter = Builders<TestClass>.Filter.Eq(x => x.AnyProperty, Value); var Filter = Builders<T>.FIlter.Eq(x => x.AnyProperty, value); public

标题可能模棱两可,但让我解释一下

我正在使用MongoDb和MongoDb的c#驱动程序,我们可以创建一个
FilterDefinition
来创建一个过滤器来获取数据,如下所示:

var Filter = Builders<TestClass>.Filter.Eq(x => x.AnyProperty, Value);
var Filter = Builders<T>.FIlter.Eq(x => x.AnyProperty, value);
 public FilterDefinition<TDocument> Eq<TField>(FieldDefinition<TDocument, TField> field, TField value);
但它不会从数据库返回结果,因为这样做:

var Filter = Builders<MyClass>.FIlter.Eq("PropertName", value);
代码中的

FIlter.Eq(x=>x.GetType().GetProperty(PropertyName),value)
,我的理解是Mongo驱动程序需要一个
表达式
,当您使用元数据(如原始情况下的
x=>x.AnyProperty

在这种情况下,您需要显式地提供
MemberExpression
,如下所示

现在,您可以向
过滤器.Eq
memberAccessExpression
,在这种情况下,如果
AnyProperty
不是
类型T
的一部分,它将在运行时失败,因为它在运行时经过验证

ExpressionTrees
中,这是对
x=>x.AnyProperty

编辑1:

查看Mongo DB驱动程序文档,以下是有关的重要详细信息,示例如下:

var builder = Builders<Widget>.Filter;
var filter = builder.Eq(widget => widget.X, 10) & builder.Lt(widget => widget.Y, 20);
在这种情况下,我们需要一个泛型类型
t文档
,它是主类和
t字段
,它是应用过滤器的字段类型,因此在您的情况下,代码应该是:

var builder = Builders<T>.Filter;

// Use makeMemberAccessExpression created above
var filter = builder.Eq(Expression.Lambda<Func<T,string>>(makeMemberAccessExpression), "<stringValue>");
var builder=Builders.Filter;
//使用上面创建的makeMemberAccessExpression
var filter=builder.Eq(Expression.Lambda(makeMemberAccessExpression));
要点:

  • 从Mongo文档中可以看出,我们有两种通用类型,
    TDocument
    TField
    ,在这里您只使用一种,因此对于上面的代码,它将被限制为字符串作为
    TField
    的类型,直到并且除非您将其设置为通用类型,这是您的选择,否则,所有字段都应为您提供的特定类型,在本例中为字符串
  • 更重要的是,该值应为您提供的类型
    TField
    ,否则它将不起作用,并在编译时失败
  • 还有另一个重载,
    Eq(FieldDefinition,TField)
    ,它将以类似的方式工作,但由于它需要
    FieldDefinition
    ,我们需要提供
    表达式作为类的一部分,这两个重载都转换为类似的代码

  • 这个错误来自哪里?是Mongo驱动程序还是你的代码,因为如果它是你的代码,那么它可能会修复,而且更复杂的是Mongo驱动程序导致了它还有
    过滤器的定义。Eq
    ,它需要什么类型的对象,我想,它是一种对象类型,我假设这不起作用,因为驱动程序试图将其转换为C#以外的查询。使用
    GetType
    当然不起作用。EntityFramework也是如此。如果查询中有.net逻辑,则无法将其转换为SQL(或其他任何形式),因此会出现错误。这只是一个假设,但对我来说是有意义的。而
    x=>x.Bla
    之所以有效,是因为x代表一个表,Bla代表一个列,因此它可以轻松地将其转换为用于查询的任何内容。请尝试
    x=>x.GetType().GetProperty(PropertyName).GetValue(x)
    ,因为它需要的是用于比较的值,而不仅仅是我头顶上的
    PropertyInfo
    ,Mongo驱动程序使用反射从MemberExpression获取属性名称
    x=>x.GetType().GetProperty(PropertyName)
    不是MemberExpression,因此无法使用。你想解决什么问题?
    Eq
    接受一个
    filterdefinition
    作为第一个参数,因此我无法传递
    memberAccessExpression
    。如果你能在问题更新中粘贴架构,我猜它需要
    MemberExpression
    ,事实上,您在实际代码中提供的Lambda是
    FilterDefinition
    您的自定义类现在您需要发布
    FieldDefinition
    的定义,请将其减少到有.Net代码的位置,而不是他们的自定义代码我需要找到另一种方法。。。。挖得太深会使事情变得更复杂。
    var builder = Builders<Widget>.Filter;
    var filter = builder.Eq(widget => widget.X, 10) & builder.Lt(widget => widget.Y, 20);
    
    public FilterDefinition<TDocument> Eq<TField>(Expression<Func<TDocument, TField>> field,TField value)
    
    var builder = Builders<T>.Filter;
    
    // Use makeMemberAccessExpression created above
    var filter = builder.Eq(Expression.Lambda<Func<T,string>>(makeMemberAccessExpression), "<stringValue>");