我有一个通用函数GetDocuments<T>
,用于查询CosmosDB API。泛型受自定义IDocument
接口的约束。目前,我正在将枚举作为参数传递给该函数,该函数确定文档的类型-但是,我的界面将文档类型作为属性,因此看来我应该能够以某种方式访问它通过另一个arg。
因为我的参数位于Expression
中,所以我不确定如何访问该值(不确定使用API访问表达式参数是否正确)。如果我有一个IDocument
作为参数,访问它似乎非常简单。
鉴于此代码,如何在不将其传递给DocumentType
的情况下访问GetDocuments<T>
?
函数定义:
public IEnumerable<T> GetDocuments<T>(Expression<Func<T, bool>> predicate, Enumerations.DocumentType type) where T : IDocument
{
var results = Client.CreateDocumentQuery<T>(GetDocumentCollectionUri(), GetFeedOptions())
.Where(predicate)
.Where(s => s.DocumentType == type)
.ToList();
return results;
}
接口定义:
public interface IDocument
{
[JsonProperty(PropertyName = "id")]
string Id { get; set; }
[JsonProperty(PropertyName = "documentType")]
Enumerations.DocumentType DocumentType { get; }
}
函数调用:
var messages = mailboxRepository.GetDocuments<MailboxMessageTemplate>(
s => s.UserId == user.ID,
Enumerations.DocumentType.MessageTemplate);
答案 0 :(得分:2)
您可以通过预先创建表达式并将其添加到查询中来做到这一点。
这是可以解决问题的表达式。
internal static Expression<Func<T, bool>> TypeSpecificExpression<T>() where T : class
{
var parameter = Expression.Parameter(typeof(IDocument));
var member = Expression.Property(parameter, nameof(IDocument.Enumerations.DocumentType));
var contant = Expression.Constant(nameof(T));
var body = Expression.Equal(member, contant);
var extra = Expression.Lambda<Func<T, bool>>(body, parameter);
return extra;
}
然后您可以简单地将方法更改为:
public IEnumerable<T> GetDocuments<T>(Expression<Func<T, bool>> predicate) where T : IDocument
{
var results = Client.CreateDocumentQuery<T>(GetDocumentCollectionUri(), GetFeedOptions())
.Where(predicate && TypeSpecificExpression())
.ToList();
return results;
}
很显然,我无权访问Enumerations.DocumentType
枚举,因此您可能需要对以下内容进行微博:var contant = Expression.Constant(nameof(T));
另一方面,您不应像在.ToList()
上那样呼叫CreateDocumentQuery
。您正在同步查询,这可能会严重影响性能。您应该使用.AsDocumentQuery()
方法来获取查询,然后在query.ExecuteNextAsync
时调用query.HasMoreResults
。
另一方面,您似乎正在尝试构建库Cosmonaut已经完成的工作,包括您刚刚询问问题的功能(您可以找到方法here) 。值得一看。
免责声明:我是宇航员
答案 1 :(得分:0)
所以您正在寻找一种将Expression<Func<T, bool>>
转换为Func<T, bool>
的方法吗?
您可以致电Compile
。
将表达式树描述的lambda表达式编译为可执行代码,并生成代表lambda表达式的委托。
var results = Client.CreateDocumentQuery<T>(GetDocumentCollectionUri(), GetFeedOptions())
.Where(predicate.Compile())
.Where(s => s.DocumentType == type)
.ToList();