我有一个TPH架构,它具有以下层次结构:
abstract class Task
{
public int A { get; set; }
}
abstract class DocumentTask
{
public virtual Document Doc { get;set; }
public int B { get; set; }
}
class DocumentTask<TDocument> : DocumentTask
where TDocument : Document, new()
{
public override TDocument Doc { get; set; }
}
/* Some classes are inherited from DocumentTask<TDocument> */
class SignTask<TDocument> : DocumentTask<TDocument>
where TDocument : Document, new()
{
public int C { get;set; }
}
我需要从指定C
的数据库中获取所有的SignTask
,但是由于我没有非泛型的SignTask,所以我不能做类似db.Where(t => t is SignTask && ((SignTask)t).C == 5)
的事情,这就是为什么我决定直接构建一个表达式树,它只用于获取SignTask〈〉类型的实体:
var taskTypes = typeof(SignTask<>).Assembly
.GetTypes()
.Where(t =>
(t?.BaseType?.IsGenericType ?? false)
&& t?.BaseType?.GetGenericTypeDefinition() == typeof(SignTask<>)).ToList();
var parameter = Expression.Parameter(typeof(Task), "e");
var body = taskTypes.Select(type => Expression.TypeIs(parameter, type))
.Aggregate<Expression>(Expression.OrElse);
var predicate = Expression.Lambda<Func<Task, bool>>(body, parameter);
var tasks = await _dbContext
.Tasks
.Where(predicate)
.ToArrayAsync();
但是我不能通过C
属性过滤它,因为我不能为没有指定泛型参数的泛型类型构建Expression.Parameter
。
1条答案
按热度按时间ars1skjm1#
如果
DocumentTask
派生自Task
,则可以执行以下操作: