2018-03-14 20:34:41 -04:00
|
|
|
|
using PoweredSoft.DynamicLinq.Helpers;
|
|
|
|
|
using System;
|
2018-03-12 23:01:41 -04:00
|
|
|
|
using System.Collections.Generic;
|
2018-03-12 23:26:41 -04:00
|
|
|
|
using System.Linq;
|
2018-03-12 23:01:41 -04:00
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace PoweredSoft.DynamicLinq.Fluent
|
|
|
|
|
{
|
2018-03-12 23:26:41 -04:00
|
|
|
|
public class SelectPart
|
|
|
|
|
{
|
|
|
|
|
public string Path { get; set; }
|
|
|
|
|
public string PropertyName { get; set; }
|
|
|
|
|
public SelectTypes SelectType { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-14 20:36:26 -04:00
|
|
|
|
public class SelectBuilder : IQueryBuilder
|
2018-03-12 23:01:41 -04:00
|
|
|
|
{
|
2018-03-12 23:26:41 -04:00
|
|
|
|
public List<SelectPart> Parts = new List<SelectPart>();
|
2018-03-13 22:01:21 -04:00
|
|
|
|
public Type DestinationType { get; set; }
|
2018-03-12 23:26:41 -04:00
|
|
|
|
public bool Empty => Parts?.Count == 0;
|
2018-03-14 20:34:41 -04:00
|
|
|
|
public IQueryable Query { get; protected set; }
|
|
|
|
|
|
|
|
|
|
public SelectBuilder(IQueryable query)
|
|
|
|
|
{
|
|
|
|
|
Query = query;
|
|
|
|
|
}
|
2018-03-12 23:26:41 -04:00
|
|
|
|
|
|
|
|
|
protected void throwIfUsedOrEmpty(string propertyName)
|
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(propertyName))
|
|
|
|
|
throw new ArgumentNullException($"{propertyName} cannot end up be empty.");
|
|
|
|
|
|
|
|
|
|
if (Parts.Any(t => t.PropertyName == propertyName))
|
|
|
|
|
throw new Exception($"{propertyName} is already used");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SelectBuilder Key(string propertyName, string path = null)
|
|
|
|
|
{
|
|
|
|
|
if (propertyName == null)
|
|
|
|
|
propertyName = path.Split('.').LastOrDefault();
|
|
|
|
|
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
Path = path == null ? "Key" : $"Key.{path}",
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.Key
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SelectBuilder Count(string propertyName)
|
|
|
|
|
{
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.Count
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SelectBuilder LongCount(string propertyName)
|
|
|
|
|
{
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.LongCount
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SelectBuilder Sum(string path, string propertyName = null)
|
|
|
|
|
{
|
|
|
|
|
if (propertyName == null)
|
|
|
|
|
propertyName = path.Split('.').LastOrDefault();
|
|
|
|
|
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
Path = path,
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.Sum
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public SelectBuilder Average(string path, string propertyName = null)
|
|
|
|
|
{
|
|
|
|
|
if (propertyName == null)
|
|
|
|
|
propertyName = path.Split('.').LastOrDefault();
|
|
|
|
|
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
Path = path,
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.Average
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2018-03-12 23:01:41 -04:00
|
|
|
|
|
2018-03-12 23:26:41 -04:00
|
|
|
|
public SelectBuilder ToList(string propertyName)
|
|
|
|
|
{
|
|
|
|
|
throwIfUsedOrEmpty(propertyName);
|
|
|
|
|
Parts.Add(new SelectPart
|
|
|
|
|
{
|
|
|
|
|
PropertyName = propertyName,
|
|
|
|
|
SelectType = SelectTypes.ToList
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
2018-03-14 20:34:41 -04:00
|
|
|
|
|
|
|
|
|
public virtual IQueryable Build()
|
|
|
|
|
{
|
|
|
|
|
if (Empty)
|
|
|
|
|
throw new Exception("No select specified, please specify at least one select path");
|
|
|
|
|
|
|
|
|
|
var partsTuple = Parts.Select(t => (selectType: t.SelectType, propertyName: t.PropertyName, path: t.Path)).ToList();
|
|
|
|
|
return QueryableHelpers.Select(Query, partsTuple, DestinationType);
|
|
|
|
|
}
|
2018-03-12 23:01:41 -04:00
|
|
|
|
}
|
|
|
|
|
}
|