Skip to content

Instantly share code, notes, and snippets.

@KANekT
Created November 29, 2016 10:41
Show Gist options
  • Save KANekT/d94630fe220869e737a91905aeb8eb8d to your computer and use it in GitHub Desktop.
Save KANekT/d94630fe220869e737a91905aeb8eb8d to your computer and use it in GitHub Desktop.
public static class AccessorCache
{
private static readonly Hashtable Accessors = new Hashtable();
private static readonly Hashtable CallSites = new Hashtable();
private static CallSite<Func<CallSite, object, object>> GetCallSiteLocked(string name)
{
var callSite = (CallSite<Func<CallSite, object, object>>)CallSites[name];
if (callSite == null)
{
CallSites[name] = callSite = CallSite<Func<CallSite, object, object>>.Create(
Binder.GetMember(CSharpBinderFlags.None, name, typeof(AccessorCache),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
}
return callSite;
}
internal static Func<dynamic, object> GetAccessor(string name)
{
var accessor = (Func<dynamic, object>)Accessors[name];
if (accessor != null)
return accessor;
lock (Accessors)
{
accessor = (Func<dynamic, object>)Accessors[name];
if (accessor != null)
return accessor;
if (name.IndexOf('.') >= 0)
{
var props = name.Split('.');
var arr = props.Select(GetCallSiteLocked).ToArray();
accessor = target =>
{
var val = (object)target;
return arr.Aggregate(val, (current, cs) => cs.Target(cs, current));
};
}
else
{
var callSite = GetCallSiteLocked(name);
accessor = target => callSite.Target(callSite, target);
}
Accessors[name] = accessor;
}
return accessor;
}
public static OrderEnum ToOrder(this string source)
{
return (string.IsNullOrEmpty(source) || source == "asc") ? OrderEnum.Asc : OrderEnum.Desc;
}
public static IOrderedEnumerable<dynamic> Order(this IEnumerable<dynamic> source, string property, OrderEnum direction = OrderEnum.Asc)
{
return direction == OrderEnum.Asc ? source.OrderBy(GetAccessor(property), Comparer<object>.Default) : source.OrderByDescending(GetAccessor(property), Comparer<object>.Default);
}
public static IOrderedEnumerable<dynamic> OrderBy(this IEnumerable<dynamic> source, string property)
{
return source.OrderBy(GetAccessor(property), Comparer<object>.Default);
}
public static IOrderedEnumerable<dynamic> OrderByDescending(this IEnumerable<dynamic> source, string property)
{
return source.OrderByDescending(GetAccessor(property), Comparer<object>.Default);
}
public static IOrderedEnumerable<dynamic> Then(this IOrderedEnumerable<dynamic> source, string property, OrderEnum direction = OrderEnum.Asc)
{
return direction == OrderEnum.Asc ? source.ThenBy(GetAccessor(property), Comparer<object>.Default) : source.ThenByDescending(GetAccessor(property), Comparer<object>.Default);
}
public static IOrderedEnumerable<dynamic> ThenBy(this IOrderedEnumerable<dynamic> source, string property)
{
return source.ThenBy(GetAccessor(property), Comparer<object>.Default);
}
public static IOrderedEnumerable<dynamic> ThenByDescending(this IOrderedEnumerable<dynamic> source, string property)
{
return source.ThenByDescending(GetAccessor(property), Comparer<object>.Default);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment