универсальный репозиторий с фильтром и порядком в include

#linq #lambda #entity-framework-core #expression #predicate

Вопрос:

Я хочу создать лямбда-выражение внутри include динамично, если TEntity реализует интерфейс локализации.

 public partial class Repositorylt;TEntitygt; : IRepositorylt;TEntitygt; where TEntity : BaseEntitylt;EsiKeygt;  {  private IQueryablelt;Articlelt;EsiKeygt;gt; BaseTable(bool noFilterLocals = true)   {  return Entities  .Include(x =gt; x.Locales  .Where(y =gt; NoFilterLocales || y.LanguageId == _workContext.WorkingLanguage.Id)  .OrderByDescending(z =gt; z.LanguageId == _workContext.WorkingLanguage.Id)  );  }  

Так что это должно выглядеть так:

 if (isILocalizedEntity)  {  var localizedType = interfaces.FirstOrDefault(x =gt;  x.IsGenericType amp;amp;  x.GetGenericTypeDefinition() == typeof(ILocalizedEntitylt;,gt;));   PropertyInfo keyProperty = typeof(TEntity).GetProperties().Single(x =gt; x.Name == "Locales");   //######   Type localeType = null;  if (typeof(TEntity).GetInterfaces().Any(x =gt; x.IsGenericType amp;amp; x.GetGenericTypeDefinition() == typeof(ILocalizedEntitylt;,gt;)))  {  var property = typeof(TEntity).GetTypeInfo().DeclaredProperties  .SingleOrDefault(p =gt; p.Name == nameof(ILocalizedEntitylt;ILocalizedLocaleEntitylt;EsiKeygt;, EsiKeygt;.Locales));   if (property != null)  {  localeType = property.PropertyType.GetTypeInfo().GenericTypeArguments.FirstOrDefault();  }  }   //item  var targetParameter = Expression.Parameter(typeof(TEntity), "item");   //locale  var localParameter = Expression.Parameter(localeType, "locale");    //languageExpression = (locale.LanguageId == languageId)  var languageProperty = localeType  .GetTypeInfo()  .GetProperty(nameof(ILocalizedLocaleEntitylt;EsiKeygt;.LanguageId));   //locale.LanguageId  var languageMemberExpression = Expression.Property(localParameter, languageProperty);   //{guid}  var languageConstantExpression = Expression.Constant(_workContext.WorkingLanguage.Id, typeof(EsiKey));   //locale.LanguageId == {guid}  var equalsLanguage = (Expression)Expression.Equal(languageMemberExpression, languageConstantExpression);   //locale =gt; locale.LanguageId == {guid}  var localeLambdaForOrdering = Expression.Lambda(equalsLanguage, localParameter);   //NoFilterLocales  var noFilterConstantExpression = Expression.Constant(NoFilterLocales, typeof(bool));     //locale.LanguageId == {guid} || NoFilterLocales  var orExpression = Expression.Or(equalsLanguage, noFilterConstantExpression);   //locale =gt; locale.LanguageId == {guid} || NoFilterLocales  var localeLambdaForWhere = Expression.Lambda(orExpression, localParameter);   var propertyName = nameof(ILocalizedEntitylt;ILocalizedLocaleEntitylt;EsiKeygt;, EsiKeygt;.Locales);   var propertyType = targetParameter.Type.GetProperty(propertyName).PropertyType.GetGenericArguments()[0];  var memberExpression = Expression.Property(targetParameter, nameof(ILocalizedEntitylt;ILocalizedLocaleEntitylt;EsiKeygt;, EsiKeygt;.Locales));  var methodInfo = typeof(Enumerable).GetMethods()  .First(m =gt; m.Name == nameof(Enumerable.Where) amp;amp; m.GetParameters().Length == 2);  methodInfo = methodInfo.MakeGenericMethod(propertyType);  var predicateWhereExpression = Expression.Call(methodInfo, memberExpression, localeLambdaForWhere);   ParameterExpression[] typeParams = new ParameterExpression[] { Expression.Parameter(typeof(, "") };  System.Reflection.PropertyInfo pi = propertyType.GetProperty(propertyName);  var predicateOrderExpression = Expression.Call(  typeof(Queryable),  "OrderBy",  new Type[] { propertyType, pi.PropertyType },  targetParameter,  Expression.Lambda(Expression.Property(typeParams[0], pi), typeParams)  );   var lambda = Expression.Lambdalt;Funclt;TEntity, boolgt;gt;(predicateOrderExpression, targetParameter);    Entities.Include(lambda);  

Но я не могу найти решение для добавления выражения orderby. Возможно, я также могу разделить на несколько добавлений, но не имею представления о решении.

Так что нужна помощь.