private void WriteLambdas(LambdaExpression lambda, TextFormatter formatter) { var lambdas = ExpressionSearcher.Search(lambda, e => e.NodeType == ExpressionType.Lambda).Cast <LambdaExpression>().DistinctBy(l => l.Name).ToList(); for (var i = 0; i < lambdas.Count; i++) { if (string.IsNullOrEmpty(lambdas[i].Name)) { throw new InvalidOperationException($"Lambda {lambdas[i]} is missing a name"); } var methodBuilder = typeBuilder.DefineMethod(lambdas[i].Name, MethodAttributes.Public | MethodAttributes.Static); lambda.Compile(); var debugLambda = GetDebugLambda(lambdas[i], formatter); debugLambda.Compile(); debugLambda.CompileToMethod(methodBuilder, pdbGenerator); if (i < lambdas.Count - 1) { formatter.WriteLine(); } } }
private bool CanEvaluateLocally(List <Expression> listInits) { foreach (var init in listInits) { var listChildren = ExpressionSearcher.Search(init, e => true); if (listChildren.Any(c => !CanBeEvaluatedLocally(c))) { return(false); } } return(true); }
private bool IsSingleCondition(Expression condition) { var subconditions = ExpressionSearcher.Search( condition, e => ConditionReducer.IsBinaryCondition(e) || ConditionReducer.IsMethodCondition(e) ); var isSingle = subconditions.Count == 1; if (!isSingle && strict) { throw Error.AmbiguousCondition(condition, subconditions); } return(isSingle); }
internal static Exception UnsupportedFilterExpression(Expression expr, Expression ignoredExpression, IllegalType illegalType) { var exprProperties = ExpressionSearcher.Search <PropertyExpression>(expr).Cast <PropertyExpression>().ToList(); var ignoredExprProperties = ExpressionSearcher.Search <PropertyExpression>(ignoredExpression).Cast <PropertyExpression>().ToList(); switch (illegalType) { //We don't reach this case because we always throw based on having multiple PropertyExpressions before //we can actually determine both expressions were the same case IllegalType.LeftRightSameProperty: if (ignoredExprProperties.Count == 0) { return(new NotSupportedException(string.Format(unsupportedFilterExpression_LeftRightZero, Clean(ignoredExpression)))); } return(new NotSupportedException(string.Format( unsupportedFilterExpression_LeftRightSame, ignoredExprProperties.First().PropertyInfo.Name, Clean(ignoredExpression), ignoredExpression.GetType() ))); case IllegalType.NotSingleProperty: return(new NotSupportedException(string.Format( unsupportedFilterExpression_NoProperty, Clean(ignoredExpression) ))); case IllegalType.AndSameProperty: return(new NotSupportedException(string.Format(unsupportedFilterExpression_AndSame, exprProperties.Single().PropertyInfo.Name))); case IllegalType.OrDifferentProperty: return(new NotSupportedException(string.Format( unsupportedFilterExpression_OrMultiple, exprProperties.Single().PropertyInfo.Name, ignoredExprProperties.Single().PropertyInfo.Name ))); case IllegalType.ExclusiveOr: return(new NotSupportedException(string.Format( unsupportedFilterExpression_ExclusiveOr, exprProperties.Single().PropertyInfo.Name ))); } throw new NotImplementedException($"Don't know how to handle illegal type '{illegalType}'"); }
private void GenerateMethods(LambdaExpression lambda) { var stringWriter = new StringWriter(); var formatter = new TextFormatter(stringWriter); var writer = new CSharpWriter(formatter, null); var usings = ExpressionSearcher.Search(lambda, e => true).Select(e => e.Type.Namespace).Distinct().ToList(); var ordered = usings.OrderBy(s => s).OrderBy(s => !s.StartsWith("System")).ToList(); foreach (var @using in ordered) { formatter.Write("using"); formatter.WriteSpace(); formatter.Write(@using); formatter.Write(";"); formatter.WriteLine(); } formatter.WriteLine(); formatter.Write("namespace"); formatter.WriteSpace(); formatter.Write(name); formatter.WriteLine(); writer.VisitBlock(() => { formatter.Write($"public class {typeBuilder.Name}"); formatter.WriteLine(); writer.VisitBlock(() => { WriteLambdas(lambda, formatter); }); formatter.WriteLine(); }); File.WriteAllText(symbolDocument.FileName, stringWriter.ToString()); }
private bool HasExtraMemberExpressions(Expression filter) { var members = ExpressionSearcher.Search(filter, e => e is MemberExpression, e => e is PropertyExpression).Cast <MemberExpression>().ToList(); var illegalMembers = members.Where(m => !LegalPropertyMember(m)).ToList(); //Catch instances where someone went (s.prop.SubProp == val) if (illegalMembers.Count > 0) { Logger.Log($"Expression contains {illegalMembers.Count} extraneous {nameof(MemberExpression)} expressions. Ignoring filter.", Indentation.Six); if (strict) { throw Error.InvalidMemberCount(filter, illegalMembers); } return(false); } return(true); }
private List <List <SearchFilter> > GetFilters(List <Expression> conditions) { Logger.Log("Evaluating filter candidates", Indentation.Four); //Remove conditions that were derived from methods that are not LinqExpressions. //For example, in Take(3).Where(s => s.Id == 1001), s.Id is a native MemberExpression //that was never transformed into a PropertyExpression. This is almost identical to //the check that is done in IsLegalFilter, however by immediately removing such candidates //we don't flag HasIllegalServerFilters, thereby allowing us to still do things such as set a Count conditions = conditions.Where(c => { var valid = ExpressionSearcher.Search <PropertyExpression>(c).Count > 0; if (!valid) { Logger.Log($"Removing condition {c} as it does not contain any property expressions", Indentation.Five); if (strict) { throw Error.InvalidPropertyCount(c, new List <PropertyExpression>()); } } return(valid); }).ToList(); var legalFilters = conditions .Where(IsLegalFilter) .Select(GetReducedCondition) .Where(IsSingleCondition) .SelectMany(GetSearchFilter).ToList(); var adjustedFilters = queryHelper?.AdjustFilters(legalFilters) ?? new List <List <SearchFilter> > { legalFilters }; return(adjustedFilters); }
private bool IsLegalFilterInternal(Expression filter) { Logger.Log($"Determining whether expression '{filter}' is a legal filter", Indentation.Five); var properties = ExpressionSearcher.Search(filter, e => e is PropertyExpression).Cast <PropertyExpression>().ToList(); if (!HasSinglePropertyExpression(filter, properties)) { return(false); } if (!HasExtraMemberExpressions(filter)) { return(false); } if (!HasOnlyLegalExpressionTypes(filter)) { return(false); } var property = properties.Single(); var parents = ExpressionSearcher.GetParents(property, filter).ToList(); if (!HasOnlyLegalCasts(property, parents)) { return(false); } if (!HasOnlyLegalParents(filter, parents)) { return(false); } Logger.Log("Filter did not match any exclusion criteria. Including filter", Indentation.Six); return(true); }
private List <PropertyExpression> GetProperties(Expression expression) { var results = ExpressionSearcher.Search <PropertyExpression>(expression); return(results.Cast <PropertyExpression>().ToList()); }
private bool IsAndOrOr(Expression node) { return(ExpressionSearcher.Search(node, e => e.NodeType == ExpressionType.AndAlso || node.NodeType == ExpressionType.OrElse).Any()); }