标题可能不明确,但让我解释一下。
我正在使用MongoDb并使用MongoDb的c#驱动程序,我们可以创建一个FilterDefinition<T>
来创建一个过滤器来获取数据,如下所示:
var Filter = Builders<TestClass>.Filter.Eq(x => x.AnyProperty, Value);
我试图将这段代码放入可重用的通用方法中,这样我就不会一次又一次地写相同的代码。我不会在此处包括整个功能,但是在功能内部,我正在尝试执行以下操作:
var Filter = Builders<T>.FIlter.Eq(x => x.AnyProperty, value);
现在的缺点是:
T
是泛型类型,这意味着它没有我想要的属性。因此,我尝试获取T
的类型并按名称获取要查找的属性,如下所示:
...FIlter.Eq(x => x.GetType().GetProperty(PropertyName), value)
这会导致异常:
无法确定x的序列化信息=> x.GetType()。GetProperty(“ UserName”)。 // UserName是属性名称
所以,我的问题是,对于泛型类型,它在lambda表达式中相当于x => x.PropertyName
,我该怎么办?
更新
忘了提,我确实尝试过这个:
var Filter = Builders<T>.FIlter.Eq("PropertName", value);
但是它不会从数据库中返回结果,就像这样:
var Filter = Builders<MyClass>.FIlter.Eq("PropertName", value);
我真的很奇怪为什么!
更新2
Filter.Eq
的定义如下:
public FilterDefinition<TDocument> Eq<TField>(FieldDefinition<TDocument, TField> field, TField value);
答案 0 :(得分:2)
在代码中
FIlter.Eq(x => x.GetType().GetProperty(PropertyName), value)
,我的不足是Mongo驱动程序期望一个Expression
,当您像原始情况下的x => x.AnyProperty
在这种情况下,您需要按以下方式明确提供
MemberExpression
var parameterExpression = Expression.Parameter(typeof(T),"x");
var memberAccessExpression = Expression.MakeMemberAccess(parameterExpression, typeof(T).GetProperty("AnyProperty"));
现在,您可以提供FIlter.Eq
值memberAccessExpression
,在这种情况下,如果AnyProperty
不属于type T
,它将在运行时失败。在运行时对其进行了验证。
在ExpressionTrees
中,这是x => x.AnyProperty
编辑1:
查看Mongo DB驱动程序文档,以下是Definitions and Builders上的重要细节,下面是一个示例:
var builder = Builders<Widget>.Filter;
var filter = builder.Eq(widget => widget.X, 10) & builder.Lt(widget => widget.Y, 20);
以下是FilterDefinitionBuilder.Eq的定义,其中公开了Eq
和其他各种过滤器:
public FilterDefinition<TDocument> Eq<TField>(Expression<Func<TDocument, TField>> field,TField value)
在这种情况下,我们需要一个通用类型TDocument
(它是主类)和TField
(它是要应用过滤器的字段的类型),因此您的情况下的代码将是:
var builder = Builders<T>.Filter;
// Use makeMemberAccessExpression created above
var filter = builder.Eq(Expression.Lambda<Func<T,string>>(makeMemberAccessExpression), "<stringValue>");
重要点:
TDocument
和TField
,在这里您只使用一种,因此使用上面的代码,它将限于字符串作为TField
的类型,直到并且除非您也将其设为通用(这是您的选择),否则所有字段均应为您提供的特定类型,在这种情况下为字符串TField
类型,否则它将不起作用并且在编译时将失败Eq<TField>(FieldDefinition<TDocument, TField>, TField)
,其工作方式类似,但是由于它期望FieldDefinition<TDocument, TField>
,因此我们需要提供Expression<Func<TDocument,TField>>
作为类的一部分,这两个重载都将转换为变成类似的代码