Просто подумал, что я вернусь к этому с решением, которое я в конечном итоге.Мои репозитории не являются полностью общими, но все методы таковы, поэтому мне нужен был способ хранения включений для любого типа сущности и возможность извлекать их при вызове методов для этого типа.
Я позаимствовализ ответа Ладислава здесь , и я могу вернуться к этому плану, чтобы каждый отдельный метод, определенный в производных репозиториях, определял свои собственные включения, так как существует достаточно различных комбинаций того, что включать и что не включать, повторяянемного кода, определяющего то же самое включение в нескольких местах, вероятно, того стоит.Но в любом случае, это текущий дизайн, и он работает ...
Базовый репозиторий:
public abstract class Repository : IQueryableRepository, IWritableRepository
{
private readonly DbContext _context;
private readonly Dictionary<Type, LambdaExpression[]> _includes = new Dictionary<Type, LambdaExpression[]>();
protected Repository(DbContextBase context)
{
_context = context;
RegisterIncludes(_includes);
}
protected abstract void RegisterIncludes(Dictionary<Type, LambdaExpression[]> includes);
protected S GetSingle<S>(Expression<Func<S, bool>> query, bool getChildren = false) where S : class
{
IQueryable<S> entities = _context.Set<S>().AsNoTracking();
if (query != null)
entities = entities.Where(query);
entities = ApplyIncludesToQuery<S>(entities, getChildren);
return entities.FirstOrDefault();
}
private IQueryable<S> ApplyIncludesToQuery<S>(IQueryable<S> entities, bool getChildren) where S : class
{
Expression<Func<S, object>>[] includes = null;
if (getChildren && _includes.ContainsKey(typeof(S)))
includes = (Expression<Func<S, object>>[])_includes[typeof(S)];
if (includes != null)
entities = includes.Aggregate(entities, (current, include) => current.Include(include));
return entities;
}
}
Производные репозитории должны только определять свои включения в одном месте, а затем при вызовеметод запроса, который вы просто указываете, хотите ли вы, чтобы дети включались или нет (см. getChildren
выше).
public class DerivedRepository : Repository
{
public DerivedRepository(DbContext context)
: base(context) { }
protected override void RegisterIncludes(Dictionary<Type, LambdaExpression[]> includes)
{
includes.Add(typeof(ParentType), new Expression<Func<ParentType, object>>[] {
p => p.SomeChildReference.SomeGrandchild,
p => p.SomeOtherChildReference
});
}
}