#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. Возможно, я также могу разделить на несколько добавлений, но не имею представления о решении.
Так что нужна помощь.