123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq.Expressions;
- using System.Runtime.Serialization;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- namespace InABox.Core
- {
- public enum SortDirection
- {
- Ascending,
- Descending
- }
- public interface ISortOrder
- {
- IEnumerable<String> ColumnNames();
- }
- public static class SortOrder
- {
- public static ISortOrder Create<T>(Type concrete, Expression<Func<T,object>> expression, SortDirection direction = SortDirection.Ascending)
- {
- if (!typeof(T).IsAssignableFrom(concrete))
- throw new Exception($"Columns: {concrete.EntityName()} does not implement {typeof(T).EntityName()}");
- var type = typeof(SortOrder<>).MakeGenericType(concrete);
- var property = CoreUtils.GetFullPropertyName(expression,".");
- var result = Activator.CreateInstance(type, property, direction );
- return result as ISortOrder;
- }
- }
-
- public class SortOrder<T> : SerializableExpression<T>, ISortOrder // where T : Entity
- {
- public SortDirection Direction { get; set; }
- public List<SortOrder<T>> Thens { get; private set; }
- //public SortOrder<T> Ascending()
- //{
- // Direction = SortOrder.Ascending;
- // return this;
- //}
- //public SortOrder<T> Descending()
- //{
- // Direction = SortOrder.Descending;
- // return this;
- //}
- public SortOrder<T> ThenBy(Expression<Func<T, object>> expression, SortDirection direction = SortDirection.Ascending)
- {
- var thenby = new SortOrder<T>(expression, direction);
- Thens.Add(thenby);
- return this;
- }
- #region Constructors
- public SortOrder()
- {
- Thens = new List<SortOrder<T>>();
- Direction = SortDirection.Ascending;
- }
- public SortOrder(Expression<Func<T, object?>> expression, SortDirection direction = SortDirection.Ascending)
- : base(expression)
- {
- Thens = new List<SortOrder<T>>();
- Direction = direction;
- }
- public SortOrder(string property, SortDirection direction = SortDirection.Ascending)
- {
- Thens = new List<SortOrder<T>>();
- Direction = direction;
- var iprop = DatabaseSchema.Property(typeof(T), property);
- Expression = iprop.Expression();
- }
- public SortOrder(SerializationInfo info, StreamingContext context)
- {
- Deserialize(info, context);
- }
- public static explicit operator SortOrder<T>(SortOrder<Entity> v)
- {
- if (v == null)
- return null;
- var json = Serialization.Serialize(v);
- json = json.Replace(typeof(Entity).EntityName(), typeof(T).EntityName());
- var result = Serialization.Deserialize<SortOrder<T>>(json);
- return result;
- }
- #endregion
- #region Display Functions
- public string AsOData()
- {
- var orderby = new Dictionary<SortDirection, string>
- {
- { SortDirection.Ascending, "asc" },
- { SortDirection.Descending, "desc" }
- };
- var prop = "";
- MemberExpression mexp = null;
- if (CoreUtils.TryFindMemberExpression(Expression, out mexp))
- prop = CoreUtils.GetFullPropertyName(mexp, "/");
- else
- prop = Expression.ToString();
- var result = string.Format("{0} {1}", prop, orderby[Direction]);
- if (Thens != null && Thens.Count > 0)
- foreach (var then in Thens)
- {
- var ThenResult = then.AsOData();
- if (!string.IsNullOrEmpty(ThenResult))
- result = string.Format("{0}, {1}", result, ThenResult);
- }
- return result;
- }
- public override string ToString()
- {
- return AsOData();
- }
- public IEnumerable<string> ColumnNames()
- {
- List<String> result = new List<string>();
- result.Add(CoreUtils.ExpressionToString(typeof(T), Expression));
- foreach (var then in Thens)
- result.AddRange(then.ColumnNames());
- return result;
- }
- #endregion
- //public Expression<Func<T,Object>> AsExpression()
- //{
- // var param = Expression.Parameter(typeof(T), "x");
- // var result = Expression.Lambda<Func<T,Object>>(Expression,param);
- // return result;
- //}
- #region Serialization
- public override void Serialize(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("Direction", Direction.ToString());
- if (Thens.Count > 0)
- info.AddValue("Thens", Thens, typeof(List<SortOrder<T>>));
- }
- public override void Deserialize(SerializationInfo info, StreamingContext context)
- {
- Direction = (SortDirection)Enum.Parse(typeof(SortDirection), (string)info.GetValue("Direction", typeof(string)));
- try
- {
- Thens = (List<SortOrder<T>>)info.GetValue("Thens", typeof(List<SortOrder<T>>));
- }
- catch
- {
- Thens = new List<SortOrder<T>>();
- }
- }
- #endregion
- }
- public class SortOrderJsonConverter : JsonConverter
- {
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
- {
- var property = CoreUtils.GetPropertyValue(value, "Expression") as MemberExpression;
- //MethodInfo mi = value.GetType().GetTypeInfo().GetMethod("ExpressionToString");
- //String prop = mi.Invoke(value, new object[] { property, true }) as String;
- var prop = CoreUtils.ExpressionToString(value.GetType().GenericTypeArguments[0], property, true);
- var dir = CoreUtils.GetPropertyValue(value, "Direction");
- writer.WriteStartObject();
- writer.WritePropertyName("Expression");
- writer.WriteValue(prop);
- writer.WritePropertyName("Direction");
- writer.WriteValue(dir);
- var thens = CoreUtils.GetPropertyValue(value, "Thens") as IList;
- if (thens != null && thens.Count > 0)
- {
- writer.WritePropertyName("Thens");
- serializer.Serialize(writer, thens);
- }
- writer.WriteEndObject();
- }
- public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
- {
- if (reader.TokenType == JsonToken.Null)
- return null;
- var data = new Dictionary<string, object>();
- while (reader.TokenType != JsonToken.EndObject && reader.Read())
- if (reader.Value != null)
- {
- var key = reader.Value.ToString();
- reader.Read();
- if (string.Equals(key, "Thens"))
- {
- var array = JArray.Load(reader);
- var thens = new List<object>();
- foreach (var item in array)
- {
- var then = ReadJson(item.CreateReader(), objectType, existingValue, serializer);
- thens.Add(then);
- //String jexp = item["Expression"].Value<String>();
- //MemberExpression exp = CoreUtils.StringToExpression(jexp) as MemberExpression;
- //var then = CreateSortOrder(
- // objectType,
- // exp.Member.Name,
- // (SortDirection)item["Direction"].Value<Int64>()
- //);
- //thens.Add(then);
- }
- data[key] = thens;
- }
- else
- {
- data[key] = reader.Value;
- }
- }
- var jprop = data["Expression"].ToString();
- var prop = CoreUtils.StringToExpression(jprop) as MemberExpression;
- var direction = (SortDirection)int.Parse(data["Direction"].ToString());
- var result = Activator.CreateInstance(objectType, CoreUtils.GetFullPropertyName(prop, "."), direction);
- if (data.ContainsKey("Thens"))
- {
- var source = data["Thens"] as List<object>;
- var target = CoreUtils.GetPropertyValue(result, "Thens") as IList;
- foreach (var srcitem in source)
- target.Add(srcitem);
- }
- return result;
- }
- public override bool CanConvert(Type objectType)
- {
- if (objectType.IsConstructedGenericType)
- {
- var ot = objectType.GetGenericTypeDefinition();
- var tt = typeof(SortOrder<>);
- if (ot == tt)
- return true;
- }
- return false;
- }
- }
- }
|