diff --git a/Squidex.sln.DotSettings b/Squidex.sln.DotSettings index 6c37eafa1..c3b776133 100644 --- a/Squidex.sln.DotSettings +++ b/Squidex.sln.DotSettings @@ -2,6 +2,7 @@ False True False + True False True True diff --git a/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs b/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs index d859af728..b34477641 100644 --- a/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcher.cs +++ b/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 { - private static readonly Dictionary> Handlers; + public delegate void ActionContextDelegate(TTarget target, T input, TContext context) where T : TIn; - static ActionContextDispatcher() + public static readonly Func On = CreateHandler(); + + public static Func 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) - .Select(ActionContextDispatcherFactory.CreateActionHandler) - .ToDictionary(h => h.Item1, h => h.Item2); - } + .GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance) + .Where(m => Helper.HasRightName(m, methodName)) + .Where(m => Helper.HasRightParameters(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 handler)) + var factoryMethod = + typeof(ActionContextDispatcher) + .GetMethod(nameof(Factory), + BindingFlags.Static | + BindingFlags.NonPublic) + .MakeGenericMethod(inputType) + .Invoke(null, new object[] { m }); + + return (inputType, factoryMethod); + }) + .ToDictionary(m => m.Item1, h => (ActionContextDelegate)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 Factory(MethodInfo methodInfo) where T : TIn + { + var handler = (ActionContextDelegate)methodInfo.CreateDelegate(typeof(ActionContextDelegate)); - return true; + return (target, input, context) => handler(target, (T)input, context); } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs b/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs deleted file mode 100644 index 19f76be73..000000000 --- a/src/Squidex.Infrastructure/Dispatching/ActionContextDispatcherFactory.cs +++ /dev/null @@ -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> CreateActionHandler(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>(inputType, (Action)handler); - } - - private static Action Factory(MethodInfo methodInfo) - { - var type = typeof(Action); - - var handler = (Action)methodInfo.CreateDelegate(type); - - return (target, input, context) => handler(target, (TIn)input, context); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs b/src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs index 7dbcfae8b..61798cade 100644 --- a/src/Squidex.Infrastructure/Dispatching/ActionDispatcher.cs +++ b/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 { - private static readonly Dictionary> Handlers; + public delegate void ActionDelegate(TTarget target, T input) where T : TIn; - static ActionDispatcher() + public static readonly Func On = CreateHandler(); + + public static Func 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) - .Select(ActionDispatcherFactory.CreateActionHandler) - .ToDictionary(h => h.Item1, h => h.Item2); - } + .GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance) + .Where(m => Helper.HasRightName(m, methodName)) + .Where(m => Helper.HasRightParameters(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 handler)) + var factoryMethod = + typeof(ActionDispatcher) + .GetMethod(nameof(Factory), + BindingFlags.Static | + BindingFlags.NonPublic) + .MakeGenericMethod(inputType) + .Invoke(null, new object[] { m }); + + return (inputType, factoryMethod); + }) + .ToDictionary(m => m.Item1, h => (ActionDelegate)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 Factory(MethodInfo methodInfo) where T : TIn + { + var handler = (ActionDelegate)methodInfo.CreateDelegate(typeof(ActionDelegate)); - return true; + return (target, input) => handler(target, (T)input); } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/ActionDispatcherFactory.cs b/src/Squidex.Infrastructure/Dispatching/ActionDispatcherFactory.cs deleted file mode 100644 index 04de5fe19..000000000 --- a/src/Squidex.Infrastructure/Dispatching/ActionDispatcherFactory.cs +++ /dev/null @@ -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> CreateActionHandler(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>(inputType, (Action)handler); - } - - private static Action Factory(MethodInfo methodInfo) - { - var type = typeof(Action); - - var handler = (Action)methodInfo.CreateDelegate(type); - - return (target, input) => handler(target, (TIn)input); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs b/src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs index b482a3273..5d55240ec 100644 --- a/src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs +++ b/src/Squidex.Infrastructure/Dispatching/DispatchExtensions.cs @@ -14,17 +14,17 @@ namespace Squidex.Infrastructure.Dispatching { public static bool DispatchAction(this TTarget target, TIn input) { - return ActionDispatcher.Dispatch(target, input); + return ActionDispatcher.On(target, input); } public static bool DispatchAction(this TTarget target, TIn input, TContext context) { - return ActionContextDispatcher.Dispatch(target, input, context); + return ActionContextDispatcher.On(target, input, context); } public static async Task DispatchActionAsync(this TTarget target, TIn input) { - var task = FuncDispatcher.Dispatch(target, input); + var task = FuncDispatcher.On(target, input); if (task == null) { @@ -38,7 +38,7 @@ namespace Squidex.Infrastructure.Dispatching public static async Task DispatchActionAsync(this TTarget target, TIn input, TContext context) { - var task = FuncContextDispatcher.Dispatch(target, input, context); + var task = FuncContextDispatcher.On(target, input, context); if (task == null) { @@ -52,28 +52,28 @@ namespace Squidex.Infrastructure.Dispatching public static TOut DispatchFunc(this TTarget target, TIn input, TOut fallback) { - var result = FuncDispatcher.Dispatch(target, input); + var result = FuncDispatcher.On(target, input); return Equals(result, default(TOut)) ? fallback : result; } public static TOut DispatchFunc(this TTarget target, TIn input, TContext context, TOut fallback) { - var result = FuncContextDispatcher.Dispatch(target, input, context); + var result = FuncContextDispatcher.On(target, input, context); return Equals(result, default(TOut)) ? fallback : result; } public static Task DispatchFuncAsync(this TTarget target, TIn input, TOut fallback) { - var result = FuncDispatcher>.Dispatch(target, input); + var result = FuncDispatcher>.On(target, input); return result ?? Task.FromResult(fallback); } public static Task DispatchFuncAsync(this TTarget target, TIn input, TContext context, TOut fallback) { - var result = FuncContextDispatcher>.Dispatch(target, input, context); + var result = FuncContextDispatcher>.On(target, input, context); return result ?? Task.FromResult(fallback); } diff --git a/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs b/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs index 53477114f..576392950 100644 --- a/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcher.cs +++ b/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 { - private static readonly Dictionary> Handlers; + public delegate TOut FuncContextDelegate(TTarget target, T input, TContext context) where T : TIn; - static FuncContextDispatcher() + public static readonly FuncContextDelegate On = CreateHandler(); + + public static FuncContextDelegate 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) - .Where(Helper.HasRightReturnType) - .Select(FuncContextDispatcherFactory.CreateFuncHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance) + .Where(m => Helper.HasRightName(m, methodName)) + .Where(m => Helper.HasRightParameters(m)) + .Where(m => Helper.HasRightReturnType(m)) + .Select(m => + { + var inputType = m.GetParameters()[0].ParameterType; + + var factoryMethod = + typeof(FuncContextDispatcher) + .GetMethod(nameof(Factory), + BindingFlags.Static | + BindingFlags.NonPublic) + .MakeGenericMethod(inputType) + .Invoke(null, new object[] { m }); + + return (inputType, factoryMethod); + }) + .ToDictionary(m => m.Item1, h => (FuncContextDelegate)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 Factory(MethodInfo methodInfo) where T : TIn { - return Handlers.TryGetValue(item.GetType(), out Func handler) ? handler(target, item, context) : default(TOut); + var handler = (FuncContextDelegate)methodInfo.CreateDelegate(typeof(FuncContextDelegate)); + + return (target, input, context) => handler(target, (T)input, context); } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs b/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs deleted file mode 100644 index faaca2ecf..000000000 --- a/src/Squidex.Infrastructure/Dispatching/FuncContextDispatcherFactory.cs +++ /dev/null @@ -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> CreateFuncHandler(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>(inputType, (Func)handler); - } - - private static Func Factory(MethodInfo methodInfo) - { - var type = typeof(Func); - - var handler = (Func)methodInfo.CreateDelegate(type); - - return (target, input, context) => handler(target, (TIn)input, context); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs b/src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs index ce18f9085..ee607b37b 100644 --- a/src/Squidex.Infrastructure/Dispatching/FuncDispatcher.cs +++ b/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 { - private static readonly Dictionary> Handlers; + public delegate TOut FuncDelegate(TTarget target, T input) where T : TIn; - static FuncDispatcher() + public static readonly FuncDelegate On = CreateHandler(); + + public static FuncDelegate 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) - .Where(Helper.HasRightReturnType) - .Select(FuncDispatcherFactory.CreateFuncHandler) - .ToDictionary(h => h.Item1, h => h.Item2); + .GetMethods( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance) + .Where(m => Helper.HasRightName(m, methodName)) + .Where(m => Helper.HasRightParameters(m)) + .Where(m => Helper.HasRightReturnType(m)) + .Select(m => + { + var inputType = m.GetParameters()[0].ParameterType; + + var factoryMethod = + typeof(FuncDispatcher) + .GetMethod(nameof(Factory), + BindingFlags.Static | + BindingFlags.NonPublic) + .MakeGenericMethod(inputType) + .Invoke(null, new object[] { m }); + + return (inputType, factoryMethod); + }) + .ToDictionary(m => m.Item1, h => (FuncDelegate)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 Factory(MethodInfo methodInfo) where T : TIn { - return Handlers.TryGetValue(item.GetType(), out Func handler) ? handler(target, item) : default(TOut); + var handler = (FuncDelegate)methodInfo.CreateDelegate(typeof(FuncDelegate)); + + return (target, input) => handler(target, (T)input); } } } \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/FuncDispatcherFactory.cs b/src/Squidex.Infrastructure/Dispatching/FuncDispatcherFactory.cs deleted file mode 100644 index d57927727..000000000 --- a/src/Squidex.Infrastructure/Dispatching/FuncDispatcherFactory.cs +++ /dev/null @@ -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> CreateFuncHandler(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>(inputType, (Func)handler); - } - - private static Func Factory(MethodInfo methodInfo) - { - var type = typeof(Func); - - var handler = (Func)methodInfo.CreateDelegate(type); - - return (target, input) => handler(target, (TIn)input); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Infrastructure/Dispatching/Helper.cs b/src/Squidex.Infrastructure/Dispatching/Helper.cs index 3cffea5a2..ebf87b328 100644 --- a/src/Squidex.Infrastructure/Dispatching/Helper.cs +++ b/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(MethodInfo method) { var parameters = method.GetParameters();