public bool TryGenerate(IPContext context, string input, out ISortParticle <TEntity> particle) { input = input.Trim(); bool isDescending = false; string name; if (input.StartsWith("-")) { isDescending = true; name = input.Substring(1).TrimStart(); } else { name = input; } if (!TryGetPropertyByName(name, out var property)) { particle = null; return(false); } particle = new ByPropertyParticle <TEntity>( property: property, descending: isDescending ); return(true); }
public static bool TryParseCsv <T>( this IPContext pContext, string input, out IEnumerable <ISortParticle <T> > particles ) where T : class { var particlesRaw = new List <ISortParticle <T> >(); var generators = pContext.GetGenerators <T, ISortParticle <T> >(); var splitInput = input .Split(','); bool wasAbleToParse = true; foreach (var sort in splitInput) { ISortParticle <T> particle = null; wasAbleToParse &= generators.Any(x => x.TryGenerate(pContext, sort, out particle)); if (!(particle is null)) { particlesRaw.Add(particle); } } particles = wasAbleToParse ? particlesRaw : Array.Empty <ISortParticle <T> >(); return(wasAbleToParse); }
public SortParticlesModelBinder(IPContext context) { if (context is null) { throw new ArgumentNullException(nameof(context)); } this.PContext = context; }
public Interface() { var x = new PContextBuilder(); x.Entity <Interface>() .Property(p => p.pContext); pContext = x.Build(); }
public Interface() { var x = new PContextBuilder(); x.Entity <Interface>() .Property(p => p.Id) .IsFilterableByName(); pContext = x.Build(); }
public bool TryGenerate(IPContext context, string input, out ISortParticle <Post> particle) { var descending = input.StartsWith('-'); var remaining = descending ? input.Substring(1) : input; if (!remaining.Trim().Equals("Popularity", System.StringComparison.OrdinalIgnoreCase)) { particle = null; return(false); } particle = new SortPostByPopularityParticle(descending); return(true); }
public bool TryGenerate(IPContext context, string input, out IFilterParticle <TEntity> particle) { input = input.Trim(); // Attempt to split the input by all "||" not enclosed in quotes or parenthesis. Regex regex = new Regex("[||](?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))(?=(((?!\\)).)*\\()|[^\\(\\)]*$)"); var splitInput = regex .Split(input) .Where(x => !string.IsNullOrWhiteSpace(x)); // If we dont end up with at least two parts, there's no OR operation here. if (splitInput.Count() < 2) { particle = null; return(false); } var trimmedInputs = splitInput.Select(x => x.Trim()); // We parse each split input and OR it to the previous one. IFilterParticle <TEntity> resultParticle = null; foreach (var filter in trimmedInputs) { var cleanFilter = filter; if (filter.StartsWith("(") && filter.EndsWith(")")) { cleanFilter = filter.Substring(1, filter.Length - 2); } if (!context.TryParseCsv(cleanFilter, out IEnumerable <IFilterParticle <TEntity> > particles)) { particle = null; return(false); } var partialResult = particles.Count() > 1 ? new AndFilterParticle <TEntity>(particles.ToArray()) : particles.Single(); resultParticle = resultParticle is null ? partialResult : new OrFilterParticle <TEntity>(resultParticle, partialResult); } particle = resultParticle; return(true); }
public static bool TryParseCsv <T>( this IPContext pContext, string input, out IEnumerable <IFilterParticle <T> > particles ) where T : class { var particlesRaw = new List <IFilterParticle <T> >(); var generators = new List <IParticleGenerator <IFilterParticle <T> > >() { // Default generators new ComplexLogicGenerator <T>() }; generators.AddRange(pContext.GetGenerators <T, IFilterParticle <T> >()); // Matching commas outside of quotes and parentheses Regex regx = new Regex("[,](?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))(?=(((?!\\)).)*\\()|[^\\(\\)]*$)"); var splitInput = regx.Split(input); bool wasAbleToParse = true; foreach (var filter in splitInput) { IFilterParticle <T> particle = null; wasAbleToParse &= generators.Any(x => x.TryGenerate(pContext, filter, out particle)); if (!(particle is null)) { particlesRaw.Add(particle); } } particles = wasAbleToParse ? particlesRaw : Array.Empty <IFilterParticle <T> >(); return(wasAbleToParse); }
public bool TryGenerate(IPContext context, string input, out IFilterParticle <TEntity> particle) { input = input.Trim(); // Attempt to capture field name from filter string. var nameMatch = Regex.Match(input, "^([A-Za-z0-9_]*)"); if (!nameMatch.Success || nameMatch.Length == 0) { particle = null; return(false); } // Validate the property by name if (!TryGetPropertyByAlias(nameMatch.Value, out PropertyInfo property)) { particle = null; return(false); } // Remove the name out of the filter string. var remaining = input.Substring(nameMatch.Length).TrimStart(); // Attempt to capture operator from filter string. // Keys are ordered by descending length to always match the longest one possible first. (eg, "!=" instead "=") var operatorKey = SymbolMapper.Symbols.FirstOrDefault(o => remaining.StartsWith(o)); if (operatorKey is null) { particle = null; return(false); } var op = SymbolMapper.Map(operatorKey); // Remove the operator out of the remaining filter string. var value = remaining.Substring(operatorKey.Length).Trim(); // If encased in double quotes, we remove them. if (value.StartsWith("\"") && value.EndsWith("\"")) { value = value.Substring(1, value.Length - 2); } try { // Attempt to convert/cast the value to the type of the property. var converter = TypeDescriptor.GetConverter(property.PropertyType); dynamic typedValue = converter.CanConvertFrom(value.GetType()) ? converter.ConvertFrom(value) : Convert.ChangeType(value, property.PropertyType); // We generate our particle Type[] typeArgs = { typeof(TEntity), property.PropertyType }; Type byPropertyParticleType = typeof(ByPropertyParticle <,>).MakeGenericType(typeArgs); particle = (IFilterParticle <TEntity>)Activator.CreateInstance(byPropertyParticleType, property, op, typedValue); return(true); } catch { particle = null; return(false); } }
// All tests are in the generic ParticlesModelBinderWorks class. // This class only provides construction of the specific model binder. protected override SortParticlesModelBinder <TestObj> Create(IPContext context) { return(new SortParticlesModelBinder <TestObj>(context)); }
abstract protected TBinder Create(IPContext context);
public IPv4Controller(IPContext context) { _context = context; }