Browse Source

Dispatcher improved.

pull/95/head
Sebastian Stehle 9 years ago
parent
commit
ebb073b4d9
  1. 1
      Squidex.sln.DotSettings
  2. 61
      src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs
  3. 41
      src/Squidex.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs
  4. 61
      src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs
  5. 41
      src/Squidex.Infrastructure/Dispatching/ActionDispatcherFactory.cs
  6. 16
      src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs
  7. 48
      src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs
  8. 41
      src/Squidex.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs
  9. 48
      src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs
  10. 41
      src/Squidex.Infrastructure/Dispatching/FuncDispatcherFactory.cs
  11. 10
      src/Squidex.Infrastructure/Dispatching/Helper.cs

1
Squidex.sln.DotSettings

@ -2,6 +2,7 @@
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002A_002A_002Ejs/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002A_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002Aapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002ADispatching_002F_002A_002E_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002A_002Fapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002A_002Fapp_002F_002A_002A_002F_002A_002Ejs/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/ExcludedFiles/FileMasksToSkip/=_002A_002Ecshtml/@EntryIndexedValue">True</s:Boolean>

61
src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs

@ -1,5 +1,5 @@
// ==========================================================================
// ActionContextDispatcher.cs
// FuncDispatcher.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
@ -7,7 +7,6 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -15,29 +14,57 @@ namespace Squidex.Infrastructure.Dispatching
{
public sealed class ActionContextDispatcher<TTarget, TIn, TContext>
{
private static readonly Dictionary<Type, Action<TTarget, object, TContext>> Handlers;
public delegate void ActionContextDelegate<in T>(TTarget target, T input, TContext context) where T : TIn;
static ActionContextDispatcher()
public static readonly Func<TTarget, TIn, TContext, bool> On = CreateHandler();
public static Func<TTarget, TIn, TContext, bool> CreateHandler(string methodName = "On")
{
Handlers =
Guard.NotNullOrEmpty(methodName, nameof(methodName));
var handlers =
typeof(TTarget)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn, TContext>)
.Select(ActionContextDispatcherFactory.CreateActionHandler<TTarget, TContext>)
.ToDictionary(h => h.Item1, h => h.Item2);
}
.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.Where(m => Helper.HasRightName(m, methodName))
.Where(m => Helper.HasRightParameters<TIn, TContext>(m))
.Where(m => Helper.HasRightVoidReturn(m))
.Select(m =>
{
var inputType = m.GetParameters()[0].ParameterType;
public static bool Dispatch(TTarget target, TIn input, TContext context)
{
if (!Handlers.TryGetValue(input.GetType(), out Action<TTarget, object, TContext> handler))
var factoryMethod =
typeof(ActionContextDispatcher<TTarget, TIn, TContext>)
.GetMethod(nameof(Factory),
BindingFlags.Static |
BindingFlags.NonPublic)
.MakeGenericMethod(inputType)
.Invoke(null, new object[] { m });
return (inputType, factoryMethod);
})
.ToDictionary(m => m.Item1, h => (ActionContextDelegate<TIn>)h.Item2);
return (target, input, context) =>
{
if (handlers.TryGetValue(input.GetType(), out var handler))
{
handler(target, input, context);
return true;
}
return false;
}
};
}
handler(target, input, context);
private static ActionContextDelegate<TIn> Factory<T>(MethodInfo methodInfo) where T : TIn
{
var handler = (ActionContextDelegate<T>)methodInfo.CreateDelegate(typeof(ActionContextDelegate<T>));
return true;
return (target, input, context) => handler(target, (T)input, context);
}
}
}

41
src/Squidex.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs

@ -1,41 +0,0 @@
// ==========================================================================
// ActionContextDispatcherFactory.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reflection;
// ReSharper disable UnusedMember.Local
namespace Squidex.Infrastructure.Dispatching
{
internal static class ActionContextDispatcherFactory
{
public static Tuple<Type, Action<TTarget, object, TContext>> CreateActionHandler<TTarget, TContext>(MethodInfo methodInfo)
{
var inputType = methodInfo.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(ActionContextDispatcherFactory)
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(TTarget), inputType, typeof(TContext));
var handler = factoryMethod.Invoke(null, new object[] { methodInfo });
return new Tuple<Type, Action<TTarget, object, TContext>>(inputType, (Action<TTarget, object, TContext>)handler);
}
private static Action<TTarget, object, TContext> Factory<TTarget, TIn, TContext>(MethodInfo methodInfo)
{
var type = typeof(Action<TTarget, TIn, TContext>);
var handler = (Action<TTarget, TIn, TContext>)methodInfo.CreateDelegate(type);
return (target, input, context) => handler(target, (TIn)input, context);
}
}
}

61
src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs

@ -1,5 +1,5 @@
// ==========================================================================
// ActionDispatcher.cs
// FuncDispatcher.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
@ -7,7 +7,6 @@
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -15,29 +14,57 @@ namespace Squidex.Infrastructure.Dispatching
{
public sealed class ActionDispatcher<TTarget, TIn>
{
private static readonly Dictionary<Type, Action<TTarget, object>> Handlers;
public delegate void ActionDelegate<in T>(TTarget target, T input) where T : TIn;
static ActionDispatcher()
public static readonly Func<TTarget, TIn, bool> On = CreateHandler();
public static Func<TTarget, TIn, bool> CreateHandler(string methodName = "On")
{
Handlers =
Guard.NotNullOrEmpty(methodName, nameof(methodName));
var handlers =
typeof(TTarget)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn>)
.Select(ActionDispatcherFactory.CreateActionHandler<TTarget>)
.ToDictionary(h => h.Item1, h => h.Item2);
}
.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.Where(m => Helper.HasRightName(m, methodName))
.Where(m => Helper.HasRightParameters<TIn>(m))
.Where(m => Helper.HasRightVoidReturn(m))
.Select(m =>
{
var inputType = m.GetParameters()[0].ParameterType;
public static bool Dispatch(TTarget target, TIn item)
{
if (!Handlers.TryGetValue(item.GetType(), out Action<TTarget, object> handler))
var factoryMethod =
typeof(ActionDispatcher<TTarget, TIn>)
.GetMethod(nameof(Factory),
BindingFlags.Static |
BindingFlags.NonPublic)
.MakeGenericMethod(inputType)
.Invoke(null, new object[] { m });
return (inputType, factoryMethod);
})
.ToDictionary(m => m.Item1, h => (ActionDelegate<TIn>)h.Item2);
return (target, input) =>
{
if (handlers.TryGetValue(input.GetType(), out var handler))
{
handler(target, input);
return true;
}
return false;
}
};
}
handler(target, item);
private static ActionDelegate<TIn> Factory<T>(MethodInfo methodInfo) where T : TIn
{
var handler = (ActionDelegate<T>)methodInfo.CreateDelegate(typeof(ActionDelegate<T>));
return true;
return (target, input) => handler(target, (T)input);
}
}
}

41
src/Squidex.Infrastructure/Dispatching/ActionDispatcherFactory.cs

@ -1,41 +0,0 @@
// ==========================================================================
// ActionDispatcherFactory.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reflection;
// ReSharper disable UnusedMember.Local
namespace Squidex.Infrastructure.Dispatching
{
internal static class ActionDispatcherFactory
{
public static Tuple<Type, Action<T, object>> CreateActionHandler<T>(MethodInfo methodInfo)
{
var inputType = methodInfo.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(ActionDispatcherFactory)
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(T), inputType);
var handler = factoryMethod.Invoke(null, new object[] { methodInfo });
return new Tuple<Type, Action<T, object>>(inputType, (Action<T, object>)handler);
}
private static Action<TTarget, object> Factory<TTarget, TIn>(MethodInfo methodInfo)
{
var type = typeof(Action<TTarget, TIn>);
var handler = (Action<TTarget, TIn>)methodInfo.CreateDelegate(type);
return (target, input) => handler(target, (TIn)input);
}
}
}

16
src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs

@ -14,17 +14,17 @@ namespace Squidex.Infrastructure.Dispatching
{
public static bool DispatchAction<TTarget, TIn>(this TTarget target, TIn input)
{
return ActionDispatcher<TTarget, TIn>.Dispatch(target, input);
return ActionDispatcher<TTarget, TIn>.On(target, input);
}
public static bool DispatchAction<TTarget, TIn, TContext>(this TTarget target, TIn input, TContext context)
{
return ActionContextDispatcher<TTarget, TIn, TContext>.Dispatch(target, input, context);
return ActionContextDispatcher<TTarget, TIn, TContext>.On(target, input, context);
}
public static async Task<bool> DispatchActionAsync<TTarget, TIn>(this TTarget target, TIn input)
{
var task = FuncDispatcher<TTarget, TIn, Task>.Dispatch(target, input);
var task = FuncDispatcher<TTarget, TIn, Task>.On(target, input);
if (task == null)
{
@ -38,7 +38,7 @@ namespace Squidex.Infrastructure.Dispatching
public static async Task<bool> DispatchActionAsync<TTarget, TIn, TContext>(this TTarget target, TIn input, TContext context)
{
var task = FuncContextDispatcher<TTarget, TIn, TContext, Task>.Dispatch(target, input, context);
var task = FuncContextDispatcher<TTarget, TIn, TContext, Task>.On(target, input, context);
if (task == null)
{
@ -52,28 +52,28 @@ namespace Squidex.Infrastructure.Dispatching
public static TOut DispatchFunc<TTarget, TIn, TOut>(this TTarget target, TIn input, TOut fallback)
{
var result = FuncDispatcher<TTarget, TIn, TOut>.Dispatch(target, input);
var result = FuncDispatcher<TTarget, TIn, TOut>.On(target, input);
return Equals(result, default(TOut)) ? fallback : result;
}
public static TOut DispatchFunc<TTarget, TIn, TContext, TOut>(this TTarget target, TIn input, TContext context, TOut fallback)
{
var result = FuncContextDispatcher<TTarget, TIn, TContext, TOut>.Dispatch(target, input, context);
var result = FuncContextDispatcher<TTarget, TIn, TContext, TOut>.On(target, input, context);
return Equals(result, default(TOut)) ? fallback : result;
}
public static Task<TOut> DispatchFuncAsync<TTarget, TIn, TOut>(this TTarget target, TIn input, TOut fallback)
{
var result = FuncDispatcher<TTarget, TIn, Task<TOut>>.Dispatch(target, input);
var result = FuncDispatcher<TTarget, TIn, Task<TOut>>.On(target, input);
return result ?? Task.FromResult(fallback);
}
public static Task<TOut> DispatchFuncAsync<TTarget, TIn, TContext, TOut>(this TTarget target, TIn input, TContext context, TOut fallback)
{
var result = FuncContextDispatcher<TTarget, TIn, TContext, Task<TOut>>.Dispatch(target, input, context);
var result = FuncContextDispatcher<TTarget, TIn, TContext, Task<TOut>>.On(target, input, context);
return result ?? Task.FromResult(fallback);
}

48
src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -15,23 +13,47 @@ namespace Squidex.Infrastructure.Dispatching
{
public sealed class FuncContextDispatcher<TTarget, TIn, TContext, TOut>
{
private static readonly Dictionary<Type, Func<TTarget, object, TContext, TOut>> Handlers;
public delegate TOut FuncContextDelegate<in T>(TTarget target, T input, TContext context) where T : TIn;
static FuncContextDispatcher()
public static readonly FuncContextDelegate<TIn> On = CreateHandler();
public static FuncContextDelegate<TIn> CreateHandler(string methodName = "On")
{
Handlers =
Guard.NotNullOrEmpty(methodName, nameof(methodName));
var handlers =
typeof(TTarget)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn, TContext>)
.Where(Helper.HasRightReturnType<TOut>)
.Select(FuncContextDispatcherFactory.CreateFuncHandler<TTarget, TContext, TOut >)
.ToDictionary(h => h.Item1, h => h.Item2);
.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.Where(m => Helper.HasRightName(m, methodName))
.Where(m => Helper.HasRightParameters<TIn, TContext>(m))
.Where(m => Helper.HasRightReturnType<TOut>(m))
.Select(m =>
{
var inputType = m.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(FuncContextDispatcher<TTarget, TIn, TContext, TOut>)
.GetMethod(nameof(Factory),
BindingFlags.Static |
BindingFlags.NonPublic)
.MakeGenericMethod(inputType)
.Invoke(null, new object[] { m });
return (inputType, factoryMethod);
})
.ToDictionary(m => m.Item1, h => (FuncContextDelegate<TIn>)h.Item2);
return (target, input, context) => handlers.TryGetValue(input.GetType(), out var handler) ? handler(target, input, context) : default(TOut);
}
public static TOut Dispatch(TTarget target, TIn item, TContext context)
private static FuncContextDelegate<TIn> Factory<T>(MethodInfo methodInfo) where T : TIn
{
return Handlers.TryGetValue(item.GetType(), out Func<TTarget, object, TContext, TOut> handler) ? handler(target, item, context) : default(TOut);
var handler = (FuncContextDelegate<T>)methodInfo.CreateDelegate(typeof(FuncContextDelegate<T>));
return (target, input, context) => handler(target, (T)input, context);
}
}
}

41
src/Squidex.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs

@ -1,41 +0,0 @@
// ==========================================================================
// FuncContextDispatcherFactory.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reflection;
// ReSharper disable UnusedMember.Local
namespace Squidex.Infrastructure.Dispatching
{
internal static class FuncContextDispatcherFactory
{
public static Tuple<Type, Func<TTarget, object, TContext, TOut>> CreateFuncHandler<TTarget, TContext, TOut>(MethodInfo methodInfo)
{
var inputType = methodInfo.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(FuncContextDispatcherFactory)
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(TTarget), inputType, typeof(TContext), methodInfo.ReturnType);
var handler = factoryMethod.Invoke(null, new object[] { methodInfo });
return new Tuple<Type, Func<TTarget, object, TContext, TOut>>(inputType, (Func<TTarget, object, TContext, TOut>)handler);
}
private static Func<TTarget, object, TContext, TOut> Factory<TTarget, TIn, TContext, TOut>(MethodInfo methodInfo)
{
var type = typeof(Func<TTarget, TIn, TContext, TOut>);
var handler = (Func<TTarget, TIn, TContext, TOut>)methodInfo.CreateDelegate(type);
return (target, input, context) => handler(target, (TIn)input, context);
}
}
}

48
src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs

@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -15,23 +13,47 @@ namespace Squidex.Infrastructure.Dispatching
{
public sealed class FuncDispatcher<TTarget, TIn, TOut>
{
private static readonly Dictionary<Type, Func<TTarget, object, TOut>> Handlers;
public delegate TOut FuncDelegate<in T>(TTarget target, T input) where T : TIn;
static FuncDispatcher()
public static readonly FuncDelegate<TIn> On = CreateHandler();
public static FuncDelegate<TIn> CreateHandler(string methodName = "On")
{
Handlers =
Guard.NotNullOrEmpty(methodName, nameof(methodName));
var handlers =
typeof(TTarget)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(Helper.HasRightName)
.Where(Helper.HasRightParameters<TIn>)
.Where(Helper.HasRightReturnType<TOut>)
.Select(FuncDispatcherFactory.CreateFuncHandler<TTarget, TOut>)
.ToDictionary(h => h.Item1, h => h.Item2);
.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.Where(m => Helper.HasRightName(m, methodName))
.Where(m => Helper.HasRightParameters<TIn>(m))
.Where(m => Helper.HasRightReturnType<TOut>(m))
.Select(m =>
{
var inputType = m.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(FuncDispatcher<TTarget, TIn, TOut>)
.GetMethod(nameof(Factory),
BindingFlags.Static |
BindingFlags.NonPublic)
.MakeGenericMethod(inputType)
.Invoke(null, new object[] { m });
return (inputType, factoryMethod);
})
.ToDictionary(m => m.Item1, h => (FuncDelegate<TIn>)h.Item2);
return (target, input) => handlers.TryGetValue(input.GetType(), out var handler) ? handler(target, input) : default(TOut);
}
public static TOut Dispatch(TTarget target, TIn item)
private static FuncDelegate<TIn> Factory<T>(MethodInfo methodInfo) where T : TIn
{
return Handlers.TryGetValue(item.GetType(), out Func<TTarget, object, TOut> handler) ? handler(target, item) : default(TOut);
var handler = (FuncDelegate<T>)methodInfo.CreateDelegate(typeof(FuncDelegate<T>));
return (target, input) => handler(target, (T)input);
}
}
}

41
src/Squidex.Infrastructure/Dispatching/FuncDispatcherFactory.cs

@ -1,41 +0,0 @@
// ==========================================================================
// FuncDispatcherFactory.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Reflection;
// ReSharper disable once UnusedMember.Local
namespace Squidex.Infrastructure.Dispatching
{
internal static class FuncDispatcherFactory
{
public static Tuple<Type, Func<TTarget, object, TReturn>> CreateFuncHandler<TTarget, TReturn>(MethodInfo methodInfo)
{
var inputType = methodInfo.GetParameters()[0].ParameterType;
var factoryMethod =
typeof(FuncDispatcherFactory)
.GetMethod("Factory", BindingFlags.Static | BindingFlags.NonPublic)
.MakeGenericMethod(typeof(TTarget), inputType, methodInfo.ReturnType);
var handler = factoryMethod.Invoke(null, new object[] { methodInfo });
return new Tuple<Type, Func<TTarget, object, TReturn>>(inputType, (Func<TTarget, object, TReturn>)handler);
}
private static Func<TTarget, object, TReturn> Factory<TTarget, TIn, TReturn>(MethodInfo methodInfo)
{
var type = typeof(Func<TTarget, TIn, TReturn>);
var handler = (Func<TTarget, TIn, TReturn>)methodInfo.CreateDelegate(type);
return (target, input) => handler(target, (TIn)input);
}
}
}

10
src/Squidex.Infrastructure/Dispatching/Helper.cs

@ -13,6 +13,11 @@ namespace Squidex.Infrastructure.Dispatching
{
internal static class Helper
{
public static bool HasRightName(MethodInfo method, string name)
{
return string.Equals(method.Name, name, StringComparison.OrdinalIgnoreCase);
}
public static bool HasRightName(MethodInfo method)
{
return string.Equals(method.Name, "On", StringComparison.OrdinalIgnoreCase);
@ -23,6 +28,11 @@ namespace Squidex.Infrastructure.Dispatching
return method.ReturnType == typeof(TOut);
}
public static bool HasRightVoidReturn(MethodInfo method)
{
return method.ReturnType == typeof(void);
}
public static bool HasRightParameters<TIn>(MethodInfo method)
{
var parameters = method.GetParameters();

Loading…
Cancel
Save