From af8222a6d43b61dd03dfe0ce8912f80bdc45bf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 22 Feb 2018 18:50:36 +0800 Subject: [PATCH 01/21] events optimization --- CatLib.Core.sln | 2 +- .../CatLib.Core.NetStandard.csproj | 5 +- .../Properties/AssemblyInfo.cs | 4 +- .../Support/Dispatcher/DispatcherTests.cs | 30 +++ src/CatLib.Core/CatLib.Core.csproj | 3 +- src/CatLib.Core/CatLib/App.cs | 50 ++-- src/CatLib.Core/CatLib/Application.cs | 11 +- .../Events/DispatcherExtend.cs | 109 +++++++-- .../CatLib/Events/GlobalDispatcher.cs | 215 ++++++++++++++++++ src/CatLib.Core/Properties/AssemblyInfo.cs | 4 +- src/CatLib.Core/Support/Events/Dispatcher.cs | 144 +++++------- src/CatLib.Core/Support/Events/Event.cs | 41 ++-- src/CatLib.Core/Support/Events/IDispatcher.cs | 8 +- src/CatLib.Core/Support/Events/IEvent.cs | 17 +- 14 files changed, 466 insertions(+), 177 deletions(-) rename src/CatLib.Core/{Support => CatLib}/Events/DispatcherExtend.cs (54%) create mode 100644 src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs diff --git a/CatLib.Core.sln b/CatLib.Core.sln index fd28704..22d9a7b 100644 --- a/CatLib.Core.sln +++ b/CatLib.Core.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 +VisualStudioVersion = 15.0.27130.2036 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CatLib.Core", "src\CatLib.Core\CatLib.Core.csproj", "{4204658E-81FD-4106-A347-890CD369C8A4}" EndProject diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj index 6c30e6f..c2e7807 100644 --- a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj +++ b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj @@ -58,6 +58,8 @@ + + @@ -84,7 +86,6 @@ - @@ -120,7 +121,7 @@ - + diff --git a/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs b/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs index d9d238b..0e93c29 100644 --- a/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs +++ b/src/CatLib.Core.Tests/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ [assembly: Guid("3c9f4024-910c-4881-a04d-34a6c3a09019")] -[assembly: AssemblyVersion("1.2.5.0")] -[assembly: AssemblyFileVersion("1.2.5.0")] +[assembly: AssemblyVersion("1.2.6.0")] +[assembly: AssemblyFileVersion("1.2.6.0")] diff --git a/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs b/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs index 34cee8d..c042585 100644 --- a/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs +++ b/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs @@ -177,6 +177,36 @@ public void TestCancelHandler() Assert.AreEqual(false, isCall); } + [TestMethod] + public void TestCancelHandlerString() + { + var app = MakeEnv(); + + var dispatcher = app.Make(); + var isCall = false; + dispatcher.Listen("event.name", (object payload) => + { + isCall = true; + Assert.AreEqual(123, payload); + return 1; + }, "1"); + dispatcher.Listen("event.name", (object payload) => + { + Assert.AreEqual(123, payload); + return 2; + }, "1"); + dispatcher.Listen("event.*", (string eventName, object payload) => + { + Assert.AreEqual(123, payload); + return 3; + }, "1"); + + App.Off("1"); + + Assert.AreEqual(null, dispatcher.TriggerHalt("event.name", 123)); + Assert.AreEqual(false, isCall); + } + [TestMethod] public void TestStopBubbling() { diff --git a/src/CatLib.Core/CatLib.Core.csproj b/src/CatLib.Core/CatLib.Core.csproj index caf0a95..82d40af 100644 --- a/src/CatLib.Core/CatLib.Core.csproj +++ b/src/CatLib.Core/CatLib.Core.csproj @@ -40,6 +40,7 @@ + @@ -55,7 +56,7 @@ - + diff --git a/src/CatLib.Core/CatLib/App.cs b/src/CatLib.Core/CatLib/App.cs index b448af9..9a6ba97 100644 --- a/src/CatLib.Core/CatLib/App.cs +++ b/src/CatLib.Core/CatLib/App.cs @@ -207,10 +207,11 @@ public static object TriggerHalt(string eventName, params object[] payloads) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, method); + return Handler.On(eventName, method, group); } /// @@ -230,10 +231,11 @@ public static IEvent On(string eventName, object target, string method = null) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, method); + return Handler.On(eventName, method, group); } /// @@ -241,10 +243,11 @@ public static IEvent On(string eventName, Action method) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, method); + return Handler.On(eventName, method, group); } /// @@ -252,10 +255,11 @@ public static IEvent On(string eventName, Action method) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, method); + return Handler.On(eventName, method, group); } /// @@ -263,10 +267,11 @@ public static IEvent On(string eventName, Action method) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, method); + return Handler.On(eventName, method, group); } /// @@ -274,10 +279,11 @@ public static IEvent On(string eventName, Action /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(string eventName, Func method) + public static IEvent Listen(string eventName, Func method, object group = null) { - return Handler.Listen(eventName, method); + return Handler.Listen(eventName, method, group); } /// @@ -285,10 +291,11 @@ public static IEvent Listen(string eventName, Func method) /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(string eventName, Func method) + public static IEvent Listen(string eventName, Func method, object group = null) { - return Handler.Listen(eventName, method); + return Handler.Listen(eventName, method, group); } /// @@ -296,10 +303,11 @@ public static IEvent Listen(string eventName, Func met /// /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(string eventName, Func method) + public static IEvent Listen(string eventName, Func method, object group = null) { - return Handler.Listen(eventName, method); + return Handler.Listen(eventName, method, group); } /// @@ -307,10 +315,11 @@ public static IEvent Listen(string eventName, Func /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(string eventName, Func method) + public static IEvent Listen(string eventName, Func method, object group = null) { - return Handler.Listen(eventName, method); + return Handler.Listen(eventName, method, group); } /// @@ -318,10 +327,11 @@ public static IEvent Listen(string eventName, Func /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(string eventName, Func method) + public static IEvent Listen(string eventName, Func method, object group = null) { - return Handler.Listen(eventName, method); + return Handler.Listen(eventName, method, group); } /// diff --git a/src/CatLib.Core/CatLib/Application.cs b/src/CatLib.Core/CatLib/Application.cs index 1d2f3b6..68dd734 100644 --- a/src/CatLib.Core/CatLib/Application.cs +++ b/src/CatLib.Core/CatLib/Application.cs @@ -345,12 +345,12 @@ public bool HasListeners(string eventName, bool strict = false) /// 注册一个事件监听器 /// /// 事件名称 - /// 调用目标 - /// 调用方法 + /// 事件调用方法 + /// 事件分组 /// 事件对象 - public IEvent On(string eventName, object target, MethodInfo method) + public IEvent On(string eventName, Func execution, object group = null) { - return Dispatcher.On(eventName, target, method); + return Dispatcher.On(eventName, execution, group); } /// @@ -432,7 +432,8 @@ protected virtual void RegisterCoreAlias() /// protected virtual void RegisterCoreService() { - this.Singleton().Alias(); + var bindable = new BindData(this, null, null, false); + this.Singleton((_, __) => new GlobalDispatcher((paramInfos, userParams) => GetDependencies(bindable, paramInfos, userParams))).Alias(); } /// diff --git a/src/CatLib.Core/Support/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs similarity index 54% rename from src/CatLib.Core/Support/Events/DispatcherExtend.cs rename to src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index c20d675..6d51378 100644 --- a/src/CatLib.Core/Support/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -10,13 +10,14 @@ */ using System; +using System.Reflection; namespace CatLib { /// /// 事件调度器扩展方法 /// - public static class DispatcherExtend + public static class CatLibDispatcherExtend { /// /// 注册一个事件监听器 @@ -32,7 +33,31 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, object ta Guard.Requires(method != string.Empty); Guard.Requires(target != null); - return dispatcher.On(eventName, target, target.GetType().GetMethod(method ?? Str.Method(eventName))); + var methodInfo = target.GetType().GetMethod(method ?? Str.Method(eventName)); + Guard.Requires(methodInfo != null); + return dispatcher.On(eventName, target, methodInfo, target); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件调度器 + /// 事件名称 + /// 事件调度目标 + /// 事件调度方法 + /// 事件分组 + /// + public static IEvent On(this IDispatcher dispatcher, string eventName, object target, MethodInfo methodInfo, object group = null) + { + Guard.NotEmptyOrNull(eventName, "eventName"); + Guard.Requires(methodInfo != null); + + if (!methodInfo.IsStatic) + { + Guard.Requires(target != null); + } + + return dispatcher.On(eventName, (_, userParams) => App.Call(target, methodInfo, userParams), group); } /// @@ -41,11 +66,15 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, object ta /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(this IDispatcher dispatcher, string eventName, Action method) + public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.On(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -54,11 +83,15 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Action me /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(this IDispatcher dispatcher, string eventName, Action method) + public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.On(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -67,11 +100,15 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Actio /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(this IDispatcher dispatcher, string eventName, Action method) + public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.On(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -80,11 +117,15 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, A /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(this IDispatcher dispatcher, string eventName, Action method) + public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.On(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -93,11 +134,15 @@ public static IEvent On(this IDispatcher dispatcher, string eventNam /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(this IDispatcher dispatcher, string eventName, Action method) + public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.On(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -106,11 +151,15 @@ public static IEvent On(this IDispatcher dispatcher, string even /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method) + public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.Listen(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -119,11 +168,15 @@ public static IEvent Listen(this IDispatcher dispatcher, string eventNa /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method) + public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.Listen(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -132,11 +185,15 @@ public static IEvent Listen(this IDispatcher dispatcher, string eve /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method) + public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.Listen(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -145,11 +202,15 @@ public static IEvent Listen(this IDispatcher dispatcher, string /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method) + public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.Listen(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } /// @@ -158,11 +219,15 @@ public static IEvent Listen(this IDispatcher dispatcher, st /// 事件调度器 /// 事件名称 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method) + public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); - return dispatcher.On(eventName, method.Target, method.Method); + var globalDispatcher = dispatcher as GlobalDispatcher; + return globalDispatcher != null + ? globalDispatcher.Listen(eventName, method, group) + : dispatcher.On(eventName, method.Target, method.Method, group); } } } diff --git a/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs b/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs new file mode 100644 index 0000000..d4edd63 --- /dev/null +++ b/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs @@ -0,0 +1,215 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * Document: http://catlib.io/ + */ + +using System; +using System.Reflection; + +namespace CatLib +{ + /// + /// 全局事件系统 + /// + internal sealed class GlobalDispatcher : Dispatcher + { + /// + /// 依赖解决器 + /// + private readonly Func dependResolved; + + /// + /// 构建一个新的全局事件系统实例 + /// + /// 依赖解决器 + public GlobalDispatcher(Func dependResolved) + { + Guard.Requires(dependResolved != null); + this.dependResolved = dependResolved; + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent On(string eventName, Action action, object group = null) + { + Guard.Requires(action != null); + return On(eventName, (e, userParams) => + { + action.Invoke(); + return null; + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent On(string eventName, Action action, object group = null) + { + Guard.Requires(action != null); + var paramInfos = action.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + action.Invoke((T0)args[0]); + return null; + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent On(string eventName, Action action, object group = null) + { + Guard.Requires(action != null); + var paramInfos = action.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + action.Invoke((T0)args[0], (T1)args[1]); + return null; + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent On(string eventName, Action action, object group = null) + { + Guard.Requires(action != null); + var paramInfos = action.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + action.Invoke((T0)args[0], (T1)args[1], (T2)args[2]); + return null; + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent On(string eventName, Action action, object group = null) + { + Guard.Requires(action != null); + var paramInfos = action.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + action.Invoke((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3]); + return null; + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent Listen(string eventName, Func func, object group = null) + { + Guard.Requires(func != null); + return On(eventName, (e, userParams) => func.Invoke(), group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent Listen(string eventName, Func func, object group = null) + { + Guard.Requires(func != null); + var paramInfos = func.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + return func.Invoke((T0)args[0]); + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent Listen(string eventName, Func func, object group = null) + { + Guard.Requires(func != null); + var paramInfos = func.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + return func.Invoke((T0)args[0], (T1)args[1]); + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent Listen(string eventName, Func func, object group = null) + { + Guard.Requires(func != null); + var paramInfos = func.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + return func.Invoke((T0)args[0], (T1)args[1], (T2)args[2]); + }, group); + } + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + public IEvent Listen(string eventName, Func func, object group = null) + { + Guard.Requires(func != null); + var paramInfos = func.Method.GetParameters(); + return On(eventName, (e, userParams) => + { + var args = dependResolved(paramInfos, userParams); + return func.Invoke((T0)args[0], (T1)args[1], (T2)args[2], (T3)args[3]); + }, group); + } + } +} diff --git a/src/CatLib.Core/Properties/AssemblyInfo.cs b/src/CatLib.Core/Properties/AssemblyInfo.cs index 421425f..3d1fa3e 100644 --- a/src/CatLib.Core/Properties/AssemblyInfo.cs +++ b/src/CatLib.Core/Properties/AssemblyInfo.cs @@ -26,8 +26,8 @@ [assembly: Guid("4204658e-81fd-4106-a347-890cd369c8a4")] -[assembly: AssemblyVersion("1.2.5.0")] -[assembly: AssemblyFileVersion("1.2.5.0")] +[assembly: AssemblyVersion("1.2.6.0")] +[assembly: AssemblyFileVersion("1.2.6.0")] [assembly: InternalsVisibleTo("Assembly-CSharp-Editor"), InternalsVisibleTo("Assembly-CSharp-Editor-firstpass"), diff --git a/src/CatLib.Core/Support/Events/Dispatcher.cs b/src/CatLib.Core/Support/Events/Dispatcher.cs index 64424f9..12f47d5 100644 --- a/src/CatLib.Core/Support/Events/Dispatcher.cs +++ b/src/CatLib.Core/Support/Events/Dispatcher.cs @@ -11,7 +11,6 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Text.RegularExpressions; namespace CatLib @@ -22,9 +21,9 @@ namespace CatLib public class Dispatcher : IDispatcher { /// - /// 调用方法目标 映射到 事件句柄 + /// 分组映射 /// - private readonly Dictionary> targetMapping; + private readonly Dictionary> groupMapping; /// /// 普通事件列表 @@ -36,19 +35,6 @@ public class Dispatcher : IDispatcher /// private readonly Dictionary>> wildcardListeners; - /// - /// 依赖注入容器 - /// - private readonly IContainer container; - - /// - /// 依赖注入容器 - /// - protected IContainer Container - { - get { return container; } - } - /// /// 同步锁 /// @@ -65,14 +51,10 @@ protected virtual object BreakFlag /// /// 构建一个事件调度器 /// - /// 依赖注入容器 - public Dispatcher(IContainer container) + public Dispatcher() { - Guard.Requires(container != null); - - this.container = container; syncRoot = new object(); - targetMapping = new Dictionary>(); + groupMapping = new Dictionary>(); listeners = new Dictionary>(); wildcardListeners = new Dictionary>>(); } @@ -91,7 +73,7 @@ public bool HasListeners(string eventName, bool strict = false) eventName = FormatEventName(eventName); lock (syncRoot) { - if (listeners.ContainsKey(eventName) + if (listeners.ContainsKey(eventName) || wildcardListeners.ContainsKey(eventName)) { return true; @@ -140,35 +122,31 @@ public object TriggerHalt(string eventName, params object[] payloads) /// 注册一个事件监听器 /// /// 事件名称 - /// 调用目标 - /// 调用方法 + /// 执行方法 + /// 事件分组,如果为Null则不进行分组 /// 事件对象 - public IEvent On(string eventName, object target, MethodInfo method) + public IEvent On(string eventName, Func execution, object group = null) { Guard.NotEmptyOrNull(eventName, "eventName"); - Guard.Requires(method != null); - if (!method.IsStatic) - { - Guard.Requires(target != null); - } + Guard.Requires(execution != null); lock (syncRoot) { eventName = FormatEventName(eventName); var result = IsWildcard(eventName) - ? SetupWildcardListen(eventName, target, method) - : SetupListen(eventName, target, method); + ? SetupWildcardListen(eventName, execution, group) + : SetupListen(eventName, execution, group); - if (target == null) + if (group == null) { return result; } List listener; - if (!targetMapping.TryGetValue(target, out listener)) + if (!groupMapping.TryGetValue(group, out listener)) { - targetMapping[target] = listener = new List(); + groupMapping[group] = listener = new List(); } listener.Add(result); @@ -183,7 +161,7 @@ public IEvent On(string eventName, object target, MethodInfo method) /// 事件解除目标 /// 如果传入的是字符串(string)将会解除对应事件名的所有事件 /// 如果传入的是事件对象(IEvent)那么解除对应事件 - /// 如果传入的是其他实例(object)会解除该实例下的所有事件 + /// 如果传入的是分组(object)会解除该分组下的所有事件 /// public void Off(object target) { @@ -201,15 +179,14 @@ public void Off(object target) if (target is string) { var eventName = FormatEventName(target.ToString()); - if (IsWildcard(eventName)) - { - DismissWildcardEventName(eventName); - } - else + var result = IsWildcard(eventName) + ? DismissWildcardEventName(eventName) + : DismissEventName(eventName); + + if (result) { - DismissEventName(eventName); + return; } - return; } DismissTargetObject(target); @@ -220,24 +197,23 @@ public void Off(object target) /// 生成事件 /// /// 事件名 - /// 目标对象 - /// 调用方法 + /// 事件执行方法 + /// 事件分组 /// 是否是通配符事件 - protected virtual IEvent MakeEvent(string eventName, object target, MethodInfo method, bool isWildcard = false) + protected virtual IEvent MakeEvent(string eventName, Func execution, object group, bool isWildcard = false) { - return new Event(eventName, target, method, MakeListener(target, method, isWildcard)); + return new Event(eventName, group, MakeListener(execution, isWildcard)); } /// /// 创建事件监听器 /// - /// 调用目标 - /// 调用方法 + /// 事件执行器 /// 是否是通配符方法 /// 事件监听器 - protected virtual Func MakeListener(object target, MethodInfo method, bool isWildcard = false) + protected virtual Func MakeListener(Func execution, bool isWildcard = false) { - return (eventName, payloads) => Container.Call(target, method, isWildcard + return (eventName, payloads) => execution(eventName, isWildcard ? Arr.Merge(new object[] { eventName }, payloads) : payloads); } @@ -252,6 +228,16 @@ protected virtual string FormatEventName(string eventName) return eventName; } + /// + /// 是否是通配符事件 + /// + /// 事件名 + /// 是否是通配符事件 + private bool IsWildcard(string eventName) + { + return eventName.IndexOf('*') != -1; + } + /// /// 调度事件 /// @@ -321,36 +307,40 @@ private IEnumerable GetListeners(string eventName) /// 根据普通事件解除相关事件 /// /// 事件名 - private void DismissEventName(string eventName) + private bool DismissEventName(string eventName) { List events; if (!listeners.TryGetValue(eventName, out events)) { - return; + return false; } foreach (var element in events.ToArray()) { Forget(element); } + + return true; } /// /// 根据通配符事件解除相关事件 /// /// 事件名 - private void DismissWildcardEventName(string eventName) + private bool DismissWildcardEventName(string eventName) { KeyValuePair> events; if (!wildcardListeners.TryGetValue(eventName, out events)) { - return; + return false; } foreach (var element in events.Value.ToArray()) { Forget(element); } + + return true; } /// @@ -360,7 +350,7 @@ private void DismissWildcardEventName(string eventName) private void DismissTargetObject(object target) { List events; - if (!targetMapping.TryGetValue(target, out events)) + if (!groupMapping.TryGetValue(target, out events)) { return; } @@ -380,16 +370,16 @@ private void Forget(IEvent target) lock (syncRoot) { List events; - if (targetMapping.TryGetValue(target.Target, out events)) + if (target.Group != null && groupMapping.TryGetValue(target.Group, out events)) { events.Remove(target); if (events.Count <= 0) { - targetMapping.Remove(target.Target); + groupMapping.Remove(target.Group); } } - if (IsWildcard(target.EventName)) + if (IsWildcard(target.Name)) { ForgetWildcardListen(target); } @@ -407,7 +397,7 @@ private void Forget(IEvent target) private void ForgetListen(IEvent target) { List events; - if (!listeners.TryGetValue(target.EventName, out events)) + if (!listeners.TryGetValue(target.Name, out events)) { return; } @@ -415,7 +405,7 @@ private void ForgetListen(IEvent target) events.Remove(target); if (events.Count <= 0) { - listeners.Remove(target.EventName); + listeners.Remove(target.Name); } } @@ -426,7 +416,7 @@ private void ForgetListen(IEvent target) private void ForgetWildcardListen(IEvent target) { KeyValuePair> wildcardEvents; - if (!wildcardListeners.TryGetValue(target.EventName, out wildcardEvents)) + if (!wildcardListeners.TryGetValue(target.Name, out wildcardEvents)) { return; } @@ -434,7 +424,7 @@ private void ForgetWildcardListen(IEvent target) wildcardEvents.Value.Remove(target); if (wildcardEvents.Value.Count <= 0) { - wildcardListeners.Remove(target.EventName); + wildcardListeners.Remove(target.Name); } } @@ -442,10 +432,10 @@ private void ForgetWildcardListen(IEvent target) /// 设定普通事件 /// /// 事件名 - /// 事件调用目标 - /// 事件调用方法 + /// 事件调用方法 + /// 事件分组 /// 监听事件 - private IEvent SetupListen(string eventName, object target, MethodInfo method) + private IEvent SetupListen(string eventName, Func execution, object group) { List listener; if (!listeners.TryGetValue(eventName, out listener)) @@ -453,7 +443,7 @@ private IEvent SetupListen(string eventName, object target, MethodInfo method) listeners[eventName] = listener = new List(); } - var output = MakeEvent(eventName, target, method); + var output = MakeEvent(eventName, execution, group); listener.Add(output); return output; } @@ -462,10 +452,10 @@ private IEvent SetupListen(string eventName, object target, MethodInfo method) /// 设定通配符事件 /// /// 事件名 - /// 事件调用目标 - /// 事件调用方法 + /// 事件调用方法 + /// 事件分组 /// 监听事件 - private IEvent SetupWildcardListen(string eventName, object target, MethodInfo method) + private IEvent SetupWildcardListen(string eventName, Func execution, object group) { KeyValuePair> listener; if (!wildcardListeners.TryGetValue(eventName, out listener)) @@ -474,19 +464,9 @@ private IEvent SetupWildcardListen(string eventName, object target, MethodInfo m new KeyValuePair>(new Regex(Str.AsteriskWildcard(eventName)), new List()); } - var output = MakeEvent(eventName, target, method, true); + var output = MakeEvent(eventName, execution, group, true); listener.Value.Add(output); return output; } - - /// - /// 是否是通配符事件 - /// - /// 事件名 - /// 是否是通配符事件 - private bool IsWildcard(string eventName) - { - return eventName.IndexOf('*') != -1; - } } } diff --git a/src/CatLib.Core/Support/Events/Event.cs b/src/CatLib.Core/Support/Events/Event.cs index 21227ea..cc62f99 100644 --- a/src/CatLib.Core/Support/Events/Event.cs +++ b/src/CatLib.Core/Support/Events/Event.cs @@ -10,7 +10,6 @@ */ using System; -using System.Reflection; namespace CatLib { @@ -20,48 +19,42 @@ namespace CatLib internal class Event : IEvent { /// - /// 事件名 + /// 原始事件名 /// - public string EventName { get; private set; } + public string Name { get; private set; } /// - /// 事件目标 + /// 事件根源对象 /// - public object Target { get; private set; } + public object Group { get; private set; } /// - /// 方法信息 + /// 依赖解决器 /// - public MethodInfo Method { get; private set; } - - /// - /// 事件调用 - /// - private readonly Func transfer; + private readonly Func execution; /// /// 创建一个事件对象 /// /// 事件名 - /// 调用方法目标 - /// 目标方法 - /// 调用方法 - public Event(string eventName, object target, MethodInfo method, Func transfer) + /// 事件分组 + /// 事件执行器 + public Event(string eventName, object group, Func execution) { - EventName = eventName; - Target = target; - Method = method; - this.transfer = transfer; + Name = eventName; + Group = group; + this.execution = execution; } /// - /// 调用事件 + /// 调用事件处理函数 /// - /// 事件名 - /// 载荷 + /// 调用事件的完整名字 + /// 事件载荷 + /// 事件处理结果 public object Call(string eventName, params object[] payloads) { - return transfer(eventName, payloads); + return execution(eventName, payloads); } } } diff --git a/src/CatLib.Core/Support/Events/IDispatcher.cs b/src/CatLib.Core/Support/Events/IDispatcher.cs index 26ebb53..d63883a 100644 --- a/src/CatLib.Core/Support/Events/IDispatcher.cs +++ b/src/CatLib.Core/Support/Events/IDispatcher.cs @@ -50,10 +50,10 @@ public interface IDispatcher /// 注册一个事件监听器 /// /// 事件名称 - /// 调用目标 - /// 调用方法 + /// 事件调用方法 + /// 事件分组,为Null则不进行分组 /// 事件对象 - IEvent On(string eventName, object target, MethodInfo method); + IEvent On(string eventName, Func execution, object group = null); /// /// 解除注册的事件监听器 @@ -62,7 +62,7 @@ public interface IDispatcher /// 事件解除目标 /// 如果传入的是字符串(string)将会解除对应事件名的所有事件 /// 如果传入的是事件对象(IEvent)那么解除对应事件 - /// 如果传入的是其他实例(object)会解除该实例下的所有事件 + /// 如果传入的是分组(object)会解除该分组下的所有事件 /// void Off(object target); } diff --git a/src/CatLib.Core/Support/Events/IEvent.cs b/src/CatLib.Core/Support/Events/IEvent.cs index a29a1b3..23870c5 100644 --- a/src/CatLib.Core/Support/Events/IEvent.cs +++ b/src/CatLib.Core/Support/Events/IEvent.cs @@ -9,8 +9,6 @@ * Document: http://catlib.io/ */ -using System.Reflection; - namespace CatLib { /// @@ -19,24 +17,19 @@ namespace CatLib public interface IEvent { /// - /// 事件名 - /// - string EventName { get; } - - /// - /// 事件目标 + /// 原始事件名 /// - object Target { get; } + string Name { get; } /// - /// 方法信息 + /// 事件分组 /// - MethodInfo Method { get; } + object Group { get; } /// /// 调用事件 /// - /// 事件名 + /// 完整的事件名 /// 载荷 /// 事件结果 object Call(string eventName, params object[] payloads); From efbaac38d19ef88242eb7c2e40ae4a20f2a97f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 22 Feb 2018 18:52:30 +0800 Subject: [PATCH 02/21] readme update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5115cb4..c29d549 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ **使用Nuget安装** ```PM -Install-Package CatLib.Core -Version 1.2.5 +Install-Package CatLib.Core -Version 1.2.6 ``` **直接下载发布版本** From c0e61af6ac8580a8d21b455c1328ded713efeee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 22 Feb 2018 18:56:33 +0800 Subject: [PATCH 03/21] dispatcher bug fixed --- src/CatLib.Core/Support/Events/Dispatcher.cs | 24 ++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/CatLib.Core/Support/Events/Dispatcher.cs b/src/CatLib.Core/Support/Events/Dispatcher.cs index 12f47d5..e123372 100644 --- a/src/CatLib.Core/Support/Events/Dispatcher.cs +++ b/src/CatLib.Core/Support/Events/Dispatcher.cs @@ -179,13 +179,13 @@ public void Off(object target) if (target is string) { var eventName = FormatEventName(target.ToString()); - var result = IsWildcard(eventName) - ? DismissWildcardEventName(eventName) - : DismissEventName(eventName); - - if (result) + if (IsWildcard(eventName)) + { + DismissWildcardEventName(eventName); + } + else { - return; + DismissEventName(eventName); } } @@ -307,40 +307,36 @@ private IEnumerable GetListeners(string eventName) /// 根据普通事件解除相关事件 /// /// 事件名 - private bool DismissEventName(string eventName) + private void DismissEventName(string eventName) { List events; if (!listeners.TryGetValue(eventName, out events)) { - return false; + return; } foreach (var element in events.ToArray()) { Forget(element); } - - return true; } /// /// 根据通配符事件解除相关事件 /// /// 事件名 - private bool DismissWildcardEventName(string eventName) + private void DismissWildcardEventName(string eventName) { KeyValuePair> events; if (!wildcardListeners.TryGetValue(eventName, out events)) { - return false; + return; } foreach (var element in events.Value.ToArray()) { Forget(element); } - - return true; } /// From bd7009a793025db5579a35d8dc0a513ff40a8ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Mon, 26 Feb 2018 11:57:47 +0800 Subject: [PATCH 04/21] dispatcher optimization --- .../CatLib/Events/DispatcherExtend.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index 6d51378..989482e 100644 --- a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -71,10 +71,14 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, object ta public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -88,10 +92,14 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Action me public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -105,10 +113,14 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Actio public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -122,10 +134,14 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, A public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -139,10 +155,14 @@ public static IEvent On(this IDispatcher dispatcher, string eventNam public static IEvent On(this IDispatcher dispatcher, string eventName, Action method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -156,10 +176,14 @@ public static IEvent On(this IDispatcher dispatcher, string even public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -173,10 +197,14 @@ public static IEvent Listen(this IDispatcher dispatcher, string eventNa public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -189,11 +217,15 @@ public static IEvent Listen(this IDispatcher dispatcher, string eve /// 事件对象 public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { +#if CATLIB_PERFORMANCE Guard.Requires(method != null); var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -207,10 +239,14 @@ public static IEvent Listen(this IDispatcher dispatcher, string public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } /// @@ -224,10 +260,14 @@ public static IEvent Listen(this IDispatcher dispatcher, st public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = dispatcher as GlobalDispatcher; return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); +#else + dispatcher.On(eventName, method.Target, method.Method, group); +#endif } } } From 1890536b2e3b202007a76f0e490f02c205a2b444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Mon, 26 Feb 2018 11:58:49 +0800 Subject: [PATCH 05/21] bug fixed --- .../CatLib/Events/DispatcherExtend.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index 989482e..75708f3 100644 --- a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -77,7 +77,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Action me ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -98,7 +98,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Actio ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -119,7 +119,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, A ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -140,7 +140,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventNam ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -161,7 +161,7 @@ public static IEvent On(this IDispatcher dispatcher, string even ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -182,7 +182,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string eventNa ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -203,7 +203,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string eve ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -224,7 +224,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -245,7 +245,7 @@ public static IEvent Listen(this IDispatcher dispatcher, st ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } @@ -266,7 +266,7 @@ public static IEvent Listen(this IDispatcher dispatcher ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); #else - dispatcher.On(eventName, method.Target, method.Method, group); + return dispatcher.On(eventName, method.Target, method.Method, group); #endif } } From 7f8534e4e542bf887e625cf4c2d9b5537aa7f1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Mon, 26 Feb 2018 17:13:04 +0800 Subject: [PATCH 06/21] dispatcher update --- .../CatLib.Core.NetStandard.csproj | 4 +- .../CatLib.Core.Tests.csproj | 1 + .../CatLib/GlobalDispatcherTests.cs | 284 ++++++++++++++++++ src/CatLib.Core/CatLib.Core.csproj | 4 +- src/CatLib.Core/CatLib/App.cs | 14 +- src/CatLib.Core/CatLib/Application.cs | 13 +- .../CatLib/Events/DispatcherExtend.cs | 39 ++- .../CatLib/Events/GlobalDispatcher.cs | 2 +- .../CatLib/Events/IGlobalDispatcher.cs | 112 +++++++ .../CatLib/Events/IOriginalDispatcher.cs | 24 ++ 10 files changed, 481 insertions(+), 16 deletions(-) create mode 100644 src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs create mode 100644 src/CatLib.Core/CatLib/Events/IGlobalDispatcher.cs create mode 100644 src/CatLib.Core/CatLib/Events/IOriginalDispatcher.cs diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj index c2e7807..0c61e1f 100644 --- a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj +++ b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj @@ -45,7 +45,7 @@ - TRACE;DEBUG;NETSTANDARD2_0;CATLIB; + TRACE;DEBUG;NETSTANDARD2_0;CATLIB;CATLIB_PERFORMANCE;NETSTANDARD2_0 @@ -60,6 +60,8 @@ + + diff --git a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj index b01e6aa..e3f89af 100644 --- a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj +++ b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj @@ -36,6 +36,7 @@ + diff --git a/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs b/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs new file mode 100644 index 0000000..f1815f7 --- /dev/null +++ b/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs @@ -0,0 +1,284 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * Document: http://catlib.io/ + */ + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CatLib.Tests +{ + [TestClass] + public class GlobalDispatcherTests + { + [TestMethod] + public void TestOn() + { + Application.New(); + + var n = string.Empty; + var a = new object[]{}; + var r = new object(); + App.On("Events.On", (name, args) => + { + n = name; + a = args; + return r; + }); + + Assert.AreEqual(r, App.TriggerHalt("Events.On","helloworld", "catlib")); + Assert.AreEqual("Events.On", n); + Assert.AreEqual("helloworld", a[0]); + Assert.AreEqual("catlib", a[1]); + } + + [TestMethod] + public void TestDispatcherGroup() + { + Application.New(); + var isCall = false; + App.On("Events", () => + { + isCall = true; + }, "catlib"); + + App.On("Events2", () => + { + isCall = true; + }, "catlib"); + + App.Trigger("Events"); + Assert.AreEqual(true, isCall); + isCall = false; + App.Trigger("Events2"); + Assert.AreEqual(true, isCall); + isCall = false; + + App.Off("catlib"); + App.Trigger("Events"); + App.Trigger("Events2"); + Assert.AreEqual(false, isCall); + } + + [TestMethod] + public void TestT1() + { + var dispatcher = new Dispatcher(); + Application.New(); + var n = 0; + dispatcher.On("Events.T1", (int num) => + { + n = num; + }); + + App.On("Events.T1",(int num) => + { + n = num + 1; + }); + + dispatcher.Listen("Events.T1.Listen", (int num) => + { + n = num; + return 100; + }); + + App.Listen("Events.T1.Listen", (int num) => + { + n = num + 1; + return 200; + }); + + var isCall = false; + dispatcher.On("Events.T0", () => + { + isCall = true; + }); + + dispatcher.Listen("Events.T0.Listen", () => + { + return 300; + }); + + App.Listen("Events.T0.Listen", () => + { + return 300; + }); + + dispatcher.Trigger("Events.T1",199478); + Assert.AreEqual(199478, n); + App.Trigger("Events.T1", 199478); + Assert.AreEqual(199479, n); + + Assert.AreEqual(100, dispatcher.TriggerHalt("Events.T1.Listen", "abc", App.Handler, 199478)); + Assert.AreEqual(199478, n); + Assert.AreEqual(200, App.TriggerHalt("Events.T1.Listen", "abcd", dispatcher, 199478)); + Assert.AreEqual(199479, n); + + dispatcher.TriggerHalt("Events.T0", "abcd", dispatcher, 199478); + Assert.AreEqual(true, isCall); + Assert.AreEqual(300, dispatcher.TriggerHalt("Events.T0.Listen", "abcd", dispatcher, 199478)); + Assert.AreEqual(300, App.TriggerHalt("Events.T0.Listen", "abcd", dispatcher, 199478)); + } + + [TestMethod] + public void TestT1_2() + { + var dispatcher = new Dispatcher(); + Application.New(); + var n = 0; + var s = string.Empty; + dispatcher.On("Events.T1_2", (int num, string hello) => + { + n = num; + s = hello; + }); + + App.On("Events.T1_2", (int num, string hello) => + { + n = num + 1; + s = hello; + }); + + dispatcher.Listen("Events.T1_2.Listen", (int num, string hello) => + { + n = num; + s = hello; + return 100; + }); + + App.Listen("Events.T1_2.Listen", (int num, string hello) => + { + n = num + 1; + s = hello; + return 200; + }); + + dispatcher.Trigger("Events.T1_2", "abc",199478); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + App.Trigger("Events.T1_2", "abcd", 199478); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + + Assert.AreEqual(100, dispatcher.TriggerHalt("Events.T1_2.Listen", "abc", App.Handler, 199478)); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + Assert.AreEqual(200, App.TriggerHalt("Events.T1_2.Listen", "abcd", dispatcher, 199478)); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + } + + [TestMethod] + public void Test1_3() + { + var dispatcher = new Dispatcher(); + Application.New(); + var n = 0; + var s = string.Empty; + dispatcher.On("Events.T1_3", (int num, string hello, IDispatcher disp) => + { + n = num; + s = hello; + Assert.AreEqual(App.Handler, disp); + }); + + App.On("Events.T1_3", (int num, string hello, IDispatcher disp) => + { + n = num + 1; + s = hello; + Assert.AreEqual(dispatcher, disp); + }); + + dispatcher.Listen("Events.T1_3.Listen", (int num, string hello, IDispatcher disp) => + { + n = num; + s = hello; + Assert.AreEqual(App.Handler, disp); + return 100; + }); + + App.Listen("Events.T1_3.Listen", (int num, string hello, IDispatcher disp) => + { + n = num + 1; + s = hello; + Assert.AreEqual(dispatcher, disp); + return 200; + }); + + dispatcher.Trigger("Events.T1_3", "abc", App.Handler, 199478); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + App.Trigger("Events.T1_3", "abcd", dispatcher, 199478); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + + Assert.AreEqual(100, dispatcher.TriggerHalt("Events.T1_3.Listen", "abc", App.Handler, 199478)); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + Assert.AreEqual(200, App.TriggerHalt("Events.T1_3.Listen", "abcd", dispatcher, 199478)); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + } + + [TestMethod] + public void Test1_4() + { + var dispatcher = new Dispatcher(); + Application.New(); + var n = 0; + var s = string.Empty; + dispatcher.On("Events.T1_4", (int num, string hello, IDispatcher disp, IApplication application) => + { + n = num; + s = hello; + Assert.AreEqual(App.Handler, disp); + Assert.AreEqual(App.Handler, application); + }); + + App.On("Events.T1_4", (int num, string hello, IDispatcher disp, IApplication application) => + { + n = num + 1; + s = hello; + Assert.AreEqual(dispatcher, disp); + Assert.AreEqual(App.Handler, application); + }); + + dispatcher.Listen("Events.T1_4.Listen", (int num, string hello, IDispatcher disp, IApplication application) => + { + n = num; + s = hello; + Assert.AreEqual(App.Handler, disp); + Assert.AreEqual(App.Handler, application); + return 100; + }); + + App.Listen("Events.T1_4.Listen", (int num, string hello, IDispatcher disp, IApplication application) => + { + n = num + 1; + s = hello; + Assert.AreEqual(dispatcher, disp); + Assert.AreEqual(App.Handler, application); + return 200; + }); + + dispatcher.Trigger("Events.T1_4", "abc", App.Handler, 199478); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + App.Trigger("Events.T1_4", "abcd", dispatcher, 199478); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + + Assert.AreEqual(100, dispatcher.TriggerHalt("Events.T1_4.Listen", "abc", App.Handler, 199478)); + Assert.AreEqual(199478, n); + Assert.AreEqual("abc", s); + Assert.AreEqual(200, App.TriggerHalt("Events.T1_4.Listen", "abcd", dispatcher, 199478)); + Assert.AreEqual(199479, n); + Assert.AreEqual("abcd", s); + } + } +} diff --git a/src/CatLib.Core/CatLib.Core.csproj b/src/CatLib.Core/CatLib.Core.csproj index 82d40af..4eb4fd0 100644 --- a/src/CatLib.Core/CatLib.Core.csproj +++ b/src/CatLib.Core/CatLib.Core.csproj @@ -17,7 +17,7 @@ full false bin\Debug\ - TRACE;DEBUG;CATLIB + TRACE;DEBUG;CATLIB;CATLIB_PERFORMANCE prompt 4 true @@ -41,6 +41,8 @@ + + diff --git a/src/CatLib.Core/CatLib/App.cs b/src/CatLib.Core/CatLib/App.cs index 9a6ba97..282ae6f 100644 --- a/src/CatLib.Core/CatLib/App.cs +++ b/src/CatLib.Core/CatLib/App.cs @@ -41,7 +41,7 @@ public static IApplication Handler { if (instance == null) { - new Application(); + Application.New(); } return instance; } @@ -202,6 +202,18 @@ public static object TriggerHalt(string eventName, params object[] payloads) return Handler.TriggerHalt(eventName, payloads); } + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件调用方法 + /// 事件分组 + /// 事件对象 + public static IEvent On(string eventName, Func execution, object group = null) + { + return Handler.On(eventName, execution, group); + } + /// /// 注册一个事件监听器 /// diff --git a/src/CatLib.Core/CatLib/Application.cs b/src/CatLib.Core/CatLib/Application.cs index 68dd734..41221e9 100644 --- a/src/CatLib.Core/CatLib/Application.cs +++ b/src/CatLib.Core/CatLib/Application.cs @@ -19,7 +19,7 @@ namespace CatLib /// /// CatLib程序 /// - public class Application : Container, IApplication + public class Application : Container, IApplication, IOriginalDispatcher { /// /// 版本号 @@ -133,7 +133,7 @@ public bool IsMainThread /// /// 事件系统 /// - private IDispatcher Dispatcher + public IDispatcher Dispatcher { get { @@ -154,6 +154,15 @@ public Application() DebugLevel = DebugLevels.Prod; } + /// + /// 构建一个新的Application实例 + /// + /// Application实例 + public static Application New() + { + return new Application(); + } + /// /// 终止CatLib框架 /// diff --git a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index 75708f3..f1b9c1e 100644 --- a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -72,7 +72,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Action me { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -93,7 +93,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, Actio { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -114,7 +114,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, A { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -135,7 +135,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventNam { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -156,7 +156,7 @@ public static IEvent On(this IDispatcher dispatcher, string even { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.On(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -177,7 +177,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string eventNa { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -198,7 +198,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string eve { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -219,7 +219,7 @@ public static IEvent Listen(this IDispatcher dispatcher, string { #if CATLIB_PERFORMANCE Guard.Requires(method != null); - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -240,7 +240,7 @@ public static IEvent Listen(this IDispatcher dispatcher, st { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -261,7 +261,7 @@ public static IEvent Listen(this IDispatcher dispatcher { Guard.Requires(method != null); #if CATLIB_PERFORMANCE - var globalDispatcher = dispatcher as GlobalDispatcher; + var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) : dispatcher.On(eventName, method.Target, method.Method, group); @@ -269,5 +269,24 @@ public static IEvent Listen(this IDispatcher dispatcher return dispatcher.On(eventName, method.Target, method.Method, group); #endif } + + /// + /// 将调度器转为全局调度器 + /// + /// + /// + internal static IGlobalDispatcher ToGlobalDispatcher(this IDispatcher dispatcher) + { + var originalDispatcher = dispatcher as IOriginalDispatcher; + var globalDispatcher = originalDispatcher == null + ? null + : originalDispatcher.Dispatcher as IGlobalDispatcher; + if (globalDispatcher != null) + { + return globalDispatcher; + } + + return dispatcher as IGlobalDispatcher; + } } } diff --git a/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs b/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs index d4edd63..4dd3cc0 100644 --- a/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs +++ b/src/CatLib.Core/CatLib/Events/GlobalDispatcher.cs @@ -17,7 +17,7 @@ namespace CatLib /// /// 全局事件系统 /// - internal sealed class GlobalDispatcher : Dispatcher + internal sealed class GlobalDispatcher : Dispatcher, IGlobalDispatcher { /// /// 依赖解决器 diff --git a/src/CatLib.Core/CatLib/Events/IGlobalDispatcher.cs b/src/CatLib.Core/CatLib/Events/IGlobalDispatcher.cs new file mode 100644 index 0000000..6f6a866 --- /dev/null +++ b/src/CatLib.Core/CatLib/Events/IGlobalDispatcher.cs @@ -0,0 +1,112 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this sender code. + * + * Document: http://catlib.io/ + */ + +using System; + +namespace CatLib +{ + /// + /// 全局事件系统 + /// + internal interface IGlobalDispatcher + { + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent On(string eventName, Action action, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent On(string eventName, Action action, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent On(string eventName, Action action, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent On(string eventName, Action action, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent On(string eventName, Action action, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent Listen(string eventName, Func func, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent Listen(string eventName, Func func, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent Listen(string eventName, Func func, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent Listen(string eventName, Func func, object group = null); + + /// + /// 注册一个事件监听器 + /// + /// 事件名称 + /// 事件处理方法 + /// 事件分组 + /// 事件对象 + IEvent Listen(string eventName, Func func, + object group = null); + } +} diff --git a/src/CatLib.Core/CatLib/Events/IOriginalDispatcher.cs b/src/CatLib.Core/CatLib/Events/IOriginalDispatcher.cs new file mode 100644 index 0000000..a429dc9 --- /dev/null +++ b/src/CatLib.Core/CatLib/Events/IOriginalDispatcher.cs @@ -0,0 +1,24 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this sender code. + * + * Document: http://catlib.io/ + */ + +namespace CatLib +{ + /// + /// 原始调度器 + /// + internal interface IOriginalDispatcher + { + /// + /// 原始调度器 + /// + IDispatcher Dispatcher { get; } + } +} From e3c49503889a731a647254ddf1a33d8f58fb6f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Mon, 26 Feb 2018 17:14:23 +0800 Subject: [PATCH 07/21] dispatcher update --- src/CatLib.Core/CatLib/Events/DispatcherExtend.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index f1b9c1e..731a686 100644 --- a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -217,8 +217,8 @@ public static IEvent Listen(this IDispatcher dispatcher, string eve /// 事件对象 public static IEvent Listen(this IDispatcher dispatcher, string eventName, Func method, object group = null) { -#if CATLIB_PERFORMANCE Guard.Requires(method != null); +#if CATLIB_PERFORMANCE var globalDispatcher = ToGlobalDispatcher(dispatcher); return globalDispatcher != null ? globalDispatcher.Listen(eventName, method, group) From c847b74a7d881a90dff1dfcc380ff5dce43adc70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Mon, 26 Feb 2018 18:14:05 +0800 Subject: [PATCH 08/21] remove using --- src/CatLib.Core/Support/Events/IDispatcher.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/CatLib.Core/Support/Events/IDispatcher.cs b/src/CatLib.Core/Support/Events/IDispatcher.cs index d63883a..3403a19 100644 --- a/src/CatLib.Core/Support/Events/IDispatcher.cs +++ b/src/CatLib.Core/Support/Events/IDispatcher.cs @@ -10,7 +10,6 @@ */ using System; -using System.Reflection; namespace CatLib { From 250d721957192f4b8a52d691a5b5cc397a8371ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Wed, 28 Feb 2018 11:50:26 +0800 Subject: [PATCH 09/21] Semantic modification --- .../CatLib/GlobalDispatcherTests.cs | 2 +- src/CatLib.Core/CatLib/App.cs | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs b/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs index f1815f7..1440137 100644 --- a/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs +++ b/src/CatLib.Core.Tests/CatLib/GlobalDispatcherTests.cs @@ -24,7 +24,7 @@ public void TestOn() var n = string.Empty; var a = new object[]{}; var r = new object(); - App.On("Events.On", (name, args) => + App.Listen("Events.On", (name, args) => { n = name; a = args; diff --git a/src/CatLib.Core/CatLib/App.cs b/src/CatLib.Core/CatLib/App.cs index 282ae6f..417bfd9 100644 --- a/src/CatLib.Core/CatLib/App.cs +++ b/src/CatLib.Core/CatLib/App.cs @@ -206,12 +206,12 @@ public static object TriggerHalt(string eventName, params object[] payloads) /// 注册一个事件监听器 /// /// 事件名称 - /// 事件调用方法 - /// 事件分组 + /// 事件调用目标 + /// 事件处理方法 /// 事件对象 - public static IEvent On(string eventName, Func execution, object group = null) + public static IEvent On(string eventName, object target, string method = null) { - return Handler.On(eventName, execution, group); + return Handler.On(eventName, target, method); } /// @@ -230,12 +230,12 @@ public static IEvent On(string eventName, Action method, object group = null) /// 注册一个事件监听器 /// /// 事件名称 - /// 事件调用目标 /// 事件处理方法 + /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, object target, string method = null) + public static IEvent On(string eventName, Action method, object group = null) { - return Handler.On(eventName, target, method); + return Handler.On(eventName, method, group); } /// @@ -245,7 +245,7 @@ public static IEvent On(string eventName, object target, string method = null) /// 事件处理方法 /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method, object group = null) + public static IEvent On(string eventName, Action method, object group = null) { return Handler.On(eventName, method, group); } @@ -257,7 +257,7 @@ public static IEvent On(string eventName, Action method, object group = /// 事件处理方法 /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method, object group = null) + public static IEvent On(string eventName, Action method, object group = null) { return Handler.On(eventName, method, group); } @@ -269,7 +269,7 @@ public static IEvent On(string eventName, Action method, object /// 事件处理方法 /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method, object group = null) + public static IEvent On(string eventName, Action method, object group = null) { return Handler.On(eventName, method, group); } @@ -278,12 +278,12 @@ public static IEvent On(string eventName, Action method, /// 注册一个事件监听器 /// /// 事件名称 - /// 事件处理方法 + /// 事件调用方法 /// 事件分组 /// 事件对象 - public static IEvent On(string eventName, Action method, object group = null) + public static IEvent Listen(string eventName, Func execution, object group = null) { - return Handler.On(eventName, method, group); + return Handler.On(eventName, execution, group); } /// From 845fd6a7ec33ca420c5771cf765690050480d17c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Wed, 28 Feb 2018 12:15:25 +0800 Subject: [PATCH 10/21] container optimization --- src/CatLib.Core/Support/Container/Container.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/CatLib.Core/Support/Container/Container.cs b/src/CatLib.Core/Support/Container/Container.cs index 23906b8..7160b8e 100644 --- a/src/CatLib.Core/Support/Container/Container.cs +++ b/src/CatLib.Core/Support/Container/Container.cs @@ -1391,13 +1391,15 @@ protected virtual object[] GetDependencies(Bindable makeServiceBindData, Paramet return null; } - var results = new List(baseParams.Length); + var results = new object[baseParams.Length]; // 获取一个参数匹配器用于筛选参数 var matcher = GetParamsMatcher(ref userParams); - foreach (var baseParam in baseParams) + for (var i = 0; i < baseParams.Length; i++) { + var baseParam = baseParams[i]; + // 使用参数匹配器对参数进行匹配,参数匹配器是最先进行的,因为他们的匹配精度是最准确的 var param = (matcher == null) ? null : matcher(baseParam); @@ -1443,10 +1445,10 @@ protected virtual object[] GetDependencies(Bindable makeServiceBindData, Paramet throw new UnresolvableException(error); } - results.Add(param); + results[i] = param; } - return results.ToArray(); + return results; } /// From ce7d100ef37477d97a09834fd658812e8193c9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 1 Mar 2018 16:30:33 +0800 Subject: [PATCH 11/21] release function api update --- .../Support/Container/ContainerHelperTests.cs | 18 +++++++++++++++-- src/CatLib.Core/CatLib/App.cs | 6 +++--- .../Support/Container/ContainerExtend.cs | 20 ++++++++++--------- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs index 727ce14..363efbc 100644 --- a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs +++ b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs @@ -315,9 +315,23 @@ public void TestReleaseWithObject() var container = new Container(); container.Instance("abc"); container.Instance(10); - Assert.AreEqual(true, container.Release("abc", 10, null)); object[] data = null; - Assert.AreEqual(true, container.Release(data)); + Assert.AreEqual(true, container.Release(ref data)); + + data = new object[] {"abc", 10}; + Assert.AreEqual(true, container.Release(ref data)); + Assert.AreEqual(true, data.Length == 0); + + data = new object[] { "abc", 10, 998 }; + Assert.AreEqual(false, container.Release(ref data)); + Assert.AreEqual(true, data.Length == 3); + + container.Instance(10); + data = new object[] { "abc", 10, 998 }; + Assert.AreEqual(false, container.Release(ref data)); + Assert.AreEqual(true, data.Length == 2); + Assert.AreEqual("abc", data[0]); + Assert.AreEqual(998, data[1]); } /// diff --git a/src/CatLib.Core/CatLib/App.cs b/src/CatLib.Core/CatLib/App.cs index 417bfd9..0e8ea61 100644 --- a/src/CatLib.Core/CatLib/App.cs +++ b/src/CatLib.Core/CatLib/App.cs @@ -1071,10 +1071,10 @@ public static bool Release() /// 根据实例对象释放静态化实例 /// /// 需要释放静态化实例对象 - /// 只要有一个没有释放成功那么返回false - public static bool Release(params object[] instances) + /// 只要有一个没有释放成功那么返回false,为没有释放掉的实例 + public static bool Release(ref object[] instances) { - return Handler.Release(instances); + return Handler.Release(ref instances); } /// diff --git a/src/CatLib.Core/Support/Container/ContainerExtend.cs b/src/CatLib.Core/Support/Container/ContainerExtend.cs index 6a7d5ce..0b3d311 100644 --- a/src/CatLib.Core/Support/Container/ContainerExtend.cs +++ b/src/CatLib.Core/Support/Container/ContainerExtend.cs @@ -493,29 +493,31 @@ public static bool Release(this IContainer container) /// /// 服务容器 /// 需要释放静态化实例对象 - /// 只要有一个没有释放成功那么返回false - public static bool Release(this IContainer container, params object[] instances) + /// 只要有一个没有释放成功那么返回false, 为没有释放掉的实例 + public static bool Release(this IContainer container, ref object[] instances) { - var released = true; if (instances == null) { - return released; + return true; } - foreach (var instance in instances) + var errorIndex = 0; + + for (var index = 0; index < instances.Length; index++) { - if (instance == null) + if (instances[index] == null) { continue; } - if (!container.Release(container.Type2Service(instance.GetType()))) + if (!container.Release(container.Type2Service(instances[index].GetType()))) { - released = false; + instances[errorIndex++] = instances[index]; } } - return released; + Array.Resize(ref instances, errorIndex); + return errorIndex <= 0; } /// From 93d77d7c14b5cfe30ff922b25b7101a61bac2fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 1 Mar 2018 16:50:26 +0800 Subject: [PATCH 12/21] release api update --- .../Support/Container/ContainerHelperTests.cs | 9 ++++++++- src/CatLib.Core/CatLib/App.cs | 5 +++-- .../Support/Container/ContainerExtend.cs | 16 ++++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs index 363efbc..d8ae88f 100644 --- a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs +++ b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs @@ -328,10 +328,17 @@ public void TestReleaseWithObject() container.Instance(10); data = new object[] { "abc", 10, 998 }; - Assert.AreEqual(false, container.Release(ref data)); + Assert.AreEqual(false, container.Release(ref data, false)); Assert.AreEqual(true, data.Length == 2); Assert.AreEqual("abc", data[0]); Assert.AreEqual(998, data[1]); + + container.Instance("abc"); + data = new object[] { 10 , "abc", 998 }; + Assert.AreEqual(false, container.Release(ref data)); + Assert.AreEqual(true, data.Length == 2); + Assert.AreEqual(10, data[0]); + Assert.AreEqual(998, data[1]); } /// diff --git a/src/CatLib.Core/CatLib/App.cs b/src/CatLib.Core/CatLib/App.cs index 0e8ea61..b2a2ed0 100644 --- a/src/CatLib.Core/CatLib/App.cs +++ b/src/CatLib.Core/CatLib/App.cs @@ -1071,10 +1071,11 @@ public static bool Release() /// 根据实例对象释放静态化实例 /// /// 需要释放静态化实例对象 + /// 以相反的顺序释放实例 /// 只要有一个没有释放成功那么返回false,为没有释放掉的实例 - public static bool Release(ref object[] instances) + public static bool Release(ref object[] instances, bool reverse = true) { - return Handler.Release(ref instances); + return Handler.Release(ref instances, reverse); } /// diff --git a/src/CatLib.Core/Support/Container/ContainerExtend.cs b/src/CatLib.Core/Support/Container/ContainerExtend.cs index 0b3d311..d448391 100644 --- a/src/CatLib.Core/Support/Container/ContainerExtend.cs +++ b/src/CatLib.Core/Support/Container/ContainerExtend.cs @@ -493,14 +493,20 @@ public static bool Release(this IContainer container) /// /// 服务容器 /// 需要释放静态化实例对象 + /// 以相反的顺序开始释放 /// 只要有一个没有释放成功那么返回false, 为没有释放掉的实例 - public static bool Release(this IContainer container, ref object[] instances) + public static bool Release(this IContainer container, ref object[] instances, bool reverse = true) { - if (instances == null) + if (instances == null || instances.Length <= 0) { return true; } + if (reverse) + { + Array.Reverse(instances); + } + var errorIndex = 0; for (var index = 0; index < instances.Length; index++) @@ -517,6 +523,12 @@ public static bool Release(this IContainer container, ref object[] instances) } Array.Resize(ref instances, errorIndex); + + if (reverse && errorIndex > 0) + { + Array.Reverse(instances); + } + return errorIndex <= 0; } From e27c65855453dd28ed33881bce59df44e3da0278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 1 Mar 2018 18:48:27 +0800 Subject: [PATCH 13/21] sorset optimization --- .../Support/Container/ContainerHelperTests.cs | 3 + .../Support/SortSet/SortSetTests.cs | 47 ++++++++++++++ src/CatLib.Core/Support/SortSet/SortSet.cs | 62 ++++++++++++++----- 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs index d8ae88f..918c26e 100644 --- a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs +++ b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs @@ -318,6 +318,9 @@ public void TestReleaseWithObject() object[] data = null; Assert.AreEqual(true, container.Release(ref data)); + data = new object[0]; + Assert.AreEqual(true, container.Release(ref data)); + data = new object[] {"abc", 10}; Assert.AreEqual(true, container.Release(ref data)); Assert.AreEqual(true, data.Length == 0); diff --git a/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs b/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs index 3786e6f..4dcb01d 100644 --- a/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs +++ b/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs @@ -21,6 +21,53 @@ namespace CatLib.Tests.Stl [TestClass] public class SortSetTests { + private class PriorityComparer : IComparer + { + public int Compare(int x, int y) + { + return y - x; + } + } + + [TestMethod] + public void TestCustomComparer() + { + var list = new SortSet(new PriorityComparer()); + + for (var i = 0; i < 10; i++) + { + list.Add(i, i); + } + + Assert.AreEqual(9, list.Shift()); + Assert.AreEqual(8, list.Shift()); + Assert.AreEqual(7, list.Shift()); + Assert.AreEqual(6, list.Shift()); + Assert.AreEqual(5, list.Shift()); + Assert.AreEqual(4, list.Shift()); + Assert.AreEqual(3, list.Shift()); + Assert.AreEqual(2, list.Shift()); + Assert.AreEqual(1, list.Shift()); + Assert.AreEqual(0, list.Shift()); + + list = new SortSet(); + for (var i = 0; i < 10; i++) + { + list.Add(i, i); + } + + Assert.AreEqual(0, list.Shift()); + Assert.AreEqual(1, list.Shift()); + Assert.AreEqual(2, list.Shift()); + Assert.AreEqual(3, list.Shift()); + Assert.AreEqual(4, list.Shift()); + Assert.AreEqual(5, list.Shift()); + Assert.AreEqual(6, list.Shift()); + Assert.AreEqual(7, list.Shift()); + Assert.AreEqual(8, list.Shift()); + Assert.AreEqual(9, list.Shift()); + } + /// /// 对象插入测试 /// diff --git a/src/CatLib.Core/Support/SortSet/SortSet.cs b/src/CatLib.Core/Support/SortSet/SortSet.cs index 8352b80..04cd704 100644 --- a/src/CatLib.Core/Support/SortSet/SortSet.cs +++ b/src/CatLib.Core/Support/SortSet/SortSet.cs @@ -222,6 +222,11 @@ public void Dispose() /// private readonly System.Random random = new System.Random(); + /// + /// 比较器 + /// + private readonly IComparer comparer; + /// /// 有序集的基数 /// @@ -260,6 +265,19 @@ public SortSet(double probable = 0.25, int maxLevel = 32) }; } + /// + /// 创建一个有序集 + /// + /// 比较器 + /// 可能出现层数的概率系数(0-1之间的数) + /// 最大层数 + public SortSet(IComparer comparer, double probable = 0.25, int maxLevel = 32) + : this(probable, maxLevel) + { + Guard.Requires(comparer != null); + this.comparer = comparer; + } + /// /// 清空SortSet /// @@ -452,7 +470,7 @@ public int GetRangeCount(TScore start, TScore end) { Guard.Requires(start != null); Guard.Requires(end != null); - Guard.Requires(start.CompareTo(end) <= 0); + Guard.Requires(Compare(start, end) <= 0); int rank = 0, bakRank = 0; SkipNode bakCursor = null; @@ -465,8 +483,8 @@ public int GetRangeCount(TScore start, TScore end) for (var i = level - 1; i >= 0; --i) { while (cursor.Level[i].Forward != null && - ((!isRight && cursor.Level[i].Forward.Score.CompareTo(start) < 0) || - (isRight && cursor.Level[i].Forward.Score.CompareTo(end) <= 0))) + ((!isRight && Compare(cursor.Level[i].Forward.Score, start) < 0) || + (isRight && Compare(cursor.Level[i].Forward.Score, end) <= 0))) { rank += cursor.Level[i].Span; cursor = cursor.Level[i].Forward; @@ -556,15 +574,15 @@ public int RemoveRangeByScore(TScore startScore, TScore stopScore) { Guard.Requires(startScore != null); Guard.Requires(stopScore != null); - Guard.Requires(startScore.CompareTo(stopScore) <= 0); + Guard.Requires(Compare(startScore, stopScore) <= 0); - int removed = 0; + var removed = 0; var update = new SkipNode[maxLevel]; var cursor = header; for (var i = level - 1; i >= 0; --i) { while (cursor.Level[i].Forward != null && - cursor.Level[i].Forward.Score.CompareTo(startScore) < 0) + Compare(cursor.Level[i].Forward.Score, startScore) < 0) { cursor = cursor.Level[i].Forward; } @@ -574,7 +592,7 @@ public int RemoveRangeByScore(TScore startScore, TScore stopScore) cursor = cursor.Level[0].Forward; while (cursor != null && - cursor.Score.CompareTo(stopScore) <= 0) + Compare(cursor.Score, stopScore) <= 0) { var next = cursor.Level[0].Forward; dict.Remove(cursor.Element); @@ -661,13 +679,13 @@ public TElement[] GetElementRangeByScore(TScore startScore, TScore stopScore) { Guard.Requires(startScore != null); Guard.Requires(stopScore != null); - Guard.Requires(startScore.CompareTo(stopScore) <= 0); + Guard.Requires(Compare(startScore, stopScore) <= 0); var cursor = header; for (var i = level - 1; i >= 0; --i) { while (cursor.Level[i].Forward != null && - cursor.Level[i].Forward.Score.CompareTo(startScore) < 0) + Compare(cursor.Level[i].Forward.Score, startScore) < 0) { cursor = cursor.Level[i].Forward; } @@ -677,7 +695,7 @@ public TElement[] GetElementRangeByScore(TScore startScore, TScore stopScore) var result = new List(); while (cursor != null && - cursor.Score.CompareTo(stopScore) <= 0) + Compare(cursor.Score, stopScore) <= 0) { result.Add(cursor.Element); cursor = cursor.Level[0].Forward; @@ -746,7 +764,7 @@ private void AddElement(TElement element, TScore score) //rank为上一级结点的跨度数作为起点 rank[i] = i == (level - 1) ? 0 : rank[i + 1]; while (cursor.Level[i].Forward != null && - (cursor.Level[i].Forward.Score.CompareTo(score) < 0)) + (Compare(cursor.Level[i].Forward.Score, score) < 0)) { rank[i] += cursor.Level[i].Span; cursor = cursor.Level[i].Forward; @@ -852,7 +870,7 @@ private bool Remove(TElement element, TScore score) for (var i = level - 1; i >= 0; --i) { while (cursor.Level[i].Forward != null && - (cursor.Level[i].Forward.Score.CompareTo(score) <= 0 && + (Compare(cursor.Level[i].Forward.Score, score) <= 0 && !cursor.Level[i].Forward.Element.Equals(element))) { cursor = cursor.Level[i].Forward; @@ -865,7 +883,7 @@ private bool Remove(TElement element, TScore score) cursor = update[0].Level[0].Forward; if (cursor == null || - cursor.Score.CompareTo(score) != 0 || + Compare(cursor.Score, score) != 0 || !cursor.Element.Equals(element)) { return false; @@ -889,7 +907,7 @@ private int GetRank(TElement element, TScore score) for (var i = level - 1; i >= 0; --i) { while (cursor.Level[i].Forward != null && - (cursor.Level[i].Forward.Score.CompareTo(score) <= 0 && + (Compare(cursor.Level[i].Forward.Score, score) <= 0 && !cursor.Level[i].Forward.Equals(element))) { rank += cursor.Level[i].Span; @@ -953,5 +971,21 @@ private int GetRandomLevel() } return (newLevel < maxLevel) ? newLevel : maxLevel; } + + /// + /// 比较左值和右值 + /// 如果左值小于右值返回值需要小于0 + /// 如果左值等于右值返回值需要等于0 + /// 如果左值大于右值返回值需要大于0 + /// + /// + /// + /// + private int Compare(TScore left, TScore right) + { + return comparer != null + ? comparer.Compare(left, right) + : left.CompareTo(right); + } } } \ No newline at end of file From d52e72718ea9ad57ae802262753c91866e8d72c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Fri, 2 Mar 2018 11:13:49 +0800 Subject: [PATCH 14/21] add service provider --- src/CatLib.Core/CatLib.Core.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CatLib.Core/CatLib.Core.csproj b/src/CatLib.Core/CatLib.Core.csproj index 4eb4fd0..e89729e 100644 --- a/src/CatLib.Core/CatLib.Core.csproj +++ b/src/CatLib.Core/CatLib.Core.csproj @@ -48,6 +48,7 @@ + From 38af48cfbe5d725bb65375c144633f3e4c3c4e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Fri, 2 Mar 2018 11:15:22 +0800 Subject: [PATCH 15/21] add ServceProvider.cs --- .../CatLib.Core.NetStandard.csproj | 1 + src/CatLib.Core/CatLib/ServiceProvider.cs | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/CatLib.Core/CatLib/ServiceProvider.cs diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj index 0c61e1f..2eeceac 100644 --- a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj +++ b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj @@ -67,6 +67,7 @@ + diff --git a/src/CatLib.Core/CatLib/ServiceProvider.cs b/src/CatLib.Core/CatLib/ServiceProvider.cs new file mode 100644 index 0000000..3601aec --- /dev/null +++ b/src/CatLib.Core/CatLib/ServiceProvider.cs @@ -0,0 +1,32 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * Document: http://catlib.io/ + */ + +namespace CatLib +{ + /// + /// 基础服务提供者 + /// + [ExcludeFromCodeCoverage] + public abstract class ServiceProvider : IServiceProvider + { + /// + /// 服务提供者初始化 + /// + public virtual void Init() + { + } + + /// + /// 当注册服务提供者 + /// + public abstract void Register(); + } +} From af9c8180f2f2d77103318f466c4efcf469ce4db5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Fri, 2 Mar 2018 14:42:13 +0800 Subject: [PATCH 16/21] dispatch update --- src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs | 1 + src/CatLib.Core/CatLib/Events/DispatcherExtend.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs b/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs index 4dcb01d..0857f00 100644 --- a/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs +++ b/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs @@ -11,6 +11,7 @@ using System; using System.Collections.Generic; +using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace CatLib.Tests.Stl diff --git a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs index 731a686..c708155 100644 --- a/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs +++ b/src/CatLib.Core/CatLib/Events/DispatcherExtend.cs @@ -33,7 +33,7 @@ public static IEvent On(this IDispatcher dispatcher, string eventName, object ta Guard.Requires(method != string.Empty); Guard.Requires(target != null); - var methodInfo = target.GetType().GetMethod(method ?? Str.Method(eventName)); + var methodInfo = target.GetType().GetMethod(method ?? Str.Method(eventName), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); Guard.Requires(methodInfo != null); return dispatcher.On(eventName, target, methodInfo, target); } From 2744b20fda91908c91e5885193e1b037df1e2919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Fri, 2 Mar 2018 14:46:32 +0800 Subject: [PATCH 17/21] add unit test --- .../Support/Dispatcher/DispatcherTests.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs b/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs index c042585..20ba6f5 100644 --- a/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs +++ b/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs @@ -30,6 +30,20 @@ private IContainer MakeEnv() return app; } + private int TestCall() + { + return 199478; + } + + [TestMethod] + public void TestProtectedFunction() + { + var app = MakeEnv(); + var dispatcher = app.Make(); + dispatcher.On("event.name", this, "TestCall"); + Assert.AreEqual(199478, dispatcher.TriggerHalt("event.name")); + } + [TestMethod] public void TestSimpleOnEvents() { From 9f8ab73a0f86b9b5b928269ad6e3deb2b87be858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 8 Mar 2018 18:47:10 +0800 Subject: [PATCH 18/21] code optimization --- .../Support/Container/ContainerTests.cs | 36 +++++++++++++++++++ .../Support/Container/Container.cs | 30 ++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs index 050aa53..519f57e 100644 --- a/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs +++ b/src/CatLib.Core.Tests/Support/Container/ContainerTests.cs @@ -22,6 +22,42 @@ namespace CatLib.Tests.Stl [TestClass] public class ContainerTest { + public class InnerExceptionClass + { + public InnerExceptionClass() + { + throw new ArgumentException("Exception in InnerExceptionClass"); + } + } + + public class TestExceptionClass + { + public TestExceptionClass() + { + new InnerExceptionClass(); + } + } + + [TestMethod] + public void TestInnerException() + { + var container = MakeContainer(); + container.Bind("TestExceptionClass", typeof(TestExceptionClass), false); + + var isThrow = false; + try + { + container.Make("TestExceptionClass"); + } + catch (Exception ex) + { + isThrow = true; + Console.WriteLine(ex.Message); + } + + Assert.AreEqual(true, isThrow); + } + #region Tag /// /// 是否可以标记服务 diff --git a/src/CatLib.Core/Support/Container/Container.cs b/src/CatLib.Core/Support/Container/Container.cs index 7160b8e..9dd9510 100644 --- a/src/CatLib.Core/Support/Container/Container.cs +++ b/src/CatLib.Core/Support/Container/Container.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using System.Text; namespace CatLib { @@ -1150,7 +1151,7 @@ protected virtual object SpeculationServiceByParamName(Bindable makeServiceBindD protected virtual string GetBuildStackDebugMessage() { var previous = string.Join(", ", BuildStack.ToArray()); - return " While building [" + previous + "]."; + return " While building stack [" + previous + "]."; } /// @@ -1165,7 +1166,7 @@ protected virtual UnresolvableException MakeBuildFaildException(string makeServi string message; if (makeServiceType != null) { - message = "Target [" + makeServiceType + "] build faild. Service is [" + makeService + "]."; + message = "Class [" + makeServiceType + "] build faild. Service is [" + makeService + "]."; } else { @@ -1173,9 +1174,34 @@ protected virtual UnresolvableException MakeBuildFaildException(string makeServi } message += GetBuildStackDebugMessage(); + message += GetInnerExceptionMessage(innerException); return new UnresolvableException(message, innerException); } + /// + /// 获取内部异常提示消息 + /// + /// 内部异常 + /// 提示消息内容 + protected virtual string GetInnerExceptionMessage(Exception innerException) + { + if (innerException == null) + { + return string.Empty; + } + + var stack = new StringBuilder(); + do + { + if (stack.Length > 0) + { + stack.Append(", "); + } + stack.Append(innerException); + } while ((innerException = innerException.InnerException) != null); + return " InnerException message stack: [" + stack + "]"; + } + /// /// 生成一个未能解决基本类型的异常 /// From eb071e9486f0694cee8a78c693a8b7d7fa6c88e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Thu, 8 Mar 2018 19:04:06 +0800 Subject: [PATCH 19/21] add cut function --- .../Support/Util/ArrTests.cs | 58 +++++++++++++++++++ src/CatLib.Core/Support/Util/Arr.cs | 44 ++++++++++++-- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/src/CatLib.Core.Tests/Support/Util/ArrTests.cs b/src/CatLib.Core.Tests/Support/Util/ArrTests.cs index 35eb714..6f9ef25 100644 --- a/src/CatLib.Core.Tests/Support/Util/ArrTests.cs +++ b/src/CatLib.Core.Tests/Support/Util/ArrTests.cs @@ -633,5 +633,63 @@ public void TestEmptyFlash() Assert.AreEqual(true, isCall); } + + [TestMethod] + public void TestCut() + { + var data = new char[] { '1', '2', '3', '4', '5' }; + + Arr.Cut(ref data, 1); + Assert.AreEqual('2', data[0]); + Assert.AreEqual(4, data.Length); + Arr.Cut(ref data, -1); + Assert.AreEqual('4', data[2]); + Assert.AreEqual(3, data.Length); + Arr.Cut(ref data, 0); + Assert.AreEqual(3, data.Length); + Arr.Cut(ref data, 10); + Assert.AreEqual(0, data.Length); + data = new char[] { '1', '2', '3', '4', '5' }; + Arr.Cut(ref data, -10); + Assert.AreEqual(0, data.Length); + data = new char[] { '1', '2', '3', '4', '5' }; + Arr.Cut(ref data, 3); + Assert.AreEqual('4', data[0]); + Assert.AreEqual(2, data.Length); + data = new char[] { '1', '2', '3', '4', '5' }; + Arr.Cut(ref data, -3); + Assert.AreEqual('2', data[1]); + Assert.AreEqual(2, data.Length); + char[] obj = null; + Arr.Cut(ref obj, 100); + obj = new char[0]; + Arr.Cut(ref obj, 100); + } + + [TestMethod] + public void TestRemove() + { + var data = new char[] { '1', '2', '3', '4', '5' }; + var result = Arr.Remove(ref data, (c) => c == '3'); + Assert.AreEqual(1, result.Length); + Assert.AreEqual('3', result[0]); + Assert.AreEqual(4, data.Length); + Assert.AreEqual('4', data[2]); + + var data2 = new int[] { 1, 2, 3, 4, 5 }; + var result2 = Arr.Remove(ref data2, (c) => c % 2 == 0); + Assert.AreEqual(2, result2.Length); + Assert.AreEqual(2, result2[0]); + Assert.AreEqual(4, result2[1]); + Assert.AreEqual(3, data2.Length); + Assert.AreEqual(1, data2[0]); + Assert.AreEqual(3, data2[1]); + Assert.AreEqual(5, data2[2]); + + var data3 = new int[0]; + var result3 = Arr.Remove(ref data3, (c) => c % 2 == 0); + Assert.AreEqual(0, result3.Length); + Assert.AreEqual(0, data3.Length); + } } } diff --git a/src/CatLib.Core/Support/Util/Arr.cs b/src/CatLib.Core/Support/Util/Arr.cs index 11f1d93..c0e4306 100644 --- a/src/CatLib.Core/Support/Util/Arr.cs +++ b/src/CatLib.Core/Support/Util/Arr.cs @@ -163,6 +163,40 @@ public static T[] Splice(ref T[] source, int start, int? length = null, T[] r return requested; } + /// + /// 修剪数组 + /// + /// 数组类型 + /// 源数组 + /// 裁剪范围,负数为从后向前修剪 + public static void Cut(ref T[] source, int count) + { + if (source == null || source.Length <= 0 || count == 0) + { + return; + } + + if (Math.Abs(count) >= source.Length) + { + if (source.Length > 0) + { + Array.Resize(ref source, 0); + } + return; + } + + if (count > 0) + { + var size = source.Length - count; + Array.Copy(source, count, source, 0, size); + Array.Resize(ref source, size); + } + else + { + Array.Resize(ref source, source.Length - Math.Abs(count)); + } + } + /// /// 将数组分为新的数组块 /// 其中每个数组的单元数目由 参数决定。最后一个数组的单元数目可能会少几个。 @@ -247,19 +281,21 @@ public static T[] Remove(ref T[] source, Predicate predicate) return new T[] { }; } - var results = new List(); - + var results = new T[source.Length]; + var n = 0; for (var i = source.Length - 1; i >= 0; i--) { if (!predicate.Invoke(source[i])) { continue; } - results.Add(source[i]); + results[n++] = source[i]; RemoveAt(ref source, i); } - return Reverse(results.ToArray()); + Array.Reverse(results, 0, n); + Array.Resize(ref results, n); + return results; } /// From 435674f718de61b4695db777a84a9213b8d1bd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Tue, 13 Mar 2018 14:08:09 +0800 Subject: [PATCH 20/21] add RingBuffer --- .../CatLib.Core.NetStandard.csproj | 2 + src/CatLib.Core/CatLib.Core.csproj | 1 + .../Support/RingBuffer/RingBuffer.cs | 346 ++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 src/CatLib.Core/Support/RingBuffer/RingBuffer.cs diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj index 2eeceac..cf208fd 100644 --- a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj +++ b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj @@ -100,6 +100,7 @@ + @@ -133,6 +134,7 @@ + diff --git a/src/CatLib.Core/CatLib.Core.csproj b/src/CatLib.Core/CatLib.Core.csproj index e89729e..7b3f85f 100644 --- a/src/CatLib.Core/CatLib.Core.csproj +++ b/src/CatLib.Core/CatLib.Core.csproj @@ -83,6 +83,7 @@ + diff --git a/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs new file mode 100644 index 0000000..933831a --- /dev/null +++ b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs @@ -0,0 +1,346 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + +namespace CatLib +{ + /// + /// 环型缓冲区 + /// + public sealed class RingBufferStream : IDisposable + { + /// + /// 容量 + /// + private readonly long capacity; + + /// + /// 缓冲区容量 + /// + public int Capacity + { + get { return (int)capacity; } + } + + /// + /// 缓冲区大小 + /// + private readonly byte[] buffer; + + /// + /// 原始数组是否可以返回给开发者 + /// + private readonly bool exposable; + + /// + /// 写入的游标 + /// + private long write; + + /// + /// 读取的游标 + /// + private long read; + + /// + /// 遮罩层 + /// 为了快速计算出,环回中的写入点 + /// + private readonly long mask; + + /// + /// 同步锁 + /// + private object syncRoot; + + /// + /// 同步锁 + /// + public object SyncRoot + { + get + { + if (syncRoot == null) + { + Interlocked.CompareExchange(ref syncRoot, new object(), null); + } + return syncRoot; + } + } + + /// + /// 可以进行读取 + /// + public bool CanRead + { + get { return GetCanReadSize() > 0; } + } + + /// + /// 是否可以进行写入 + /// + public bool CanWrite() + { + return CanWrite(1); + } + + /// + /// 是否可以进行写入 + /// + /// 指定的长度 + public bool CanWrite(int count) + { + return GetCanWriteSize() >= count; + } + + /// + /// 构建一个新的环型缓冲区实例 + /// + /// 容量 + /// 是否可以访问内部数组 + public RingBufferStream(int capacity, bool exposable = true) + { + buffer = new byte[this.capacity = GetPrime(capacity)]; + mask = this.capacity - 1; + write = 0; + read = 0; + this.exposable = exposable; + } + + /// + /// 获取环型缓冲区的原始数组 + /// + /// 原始数组 + public byte[] GetBuffer() + { + if (!exposable) + { + throw new UnauthorizedAccessException("Unable to access original array"); + } + return buffer; + } + + /// + /// 将可以读取的数据全部返回 + /// + /// 可以读取的数据 + public byte[] Read() + { + var readSize = GetCanReadSize(); + if (readSize <= 0) + { + return null; + } + + var result = new byte[readSize]; + Read(result); + return result; + } + + /// + /// 将数据读取到中 + /// + /// 输出的数据 + /// 实际输出的长度 + public int Read(byte[] buffer) + { + Guard.Requires(buffer != null); + return Read(buffer, 0, buffer.Length); + } + + /// + /// 将数据读取到中 + /// + /// 输出的数据 + /// 输出数组偏移多少作为起始 + /// 实际输出的长度 + public int Read(byte[] buffer, int offset) + { + Guard.Requires(buffer != null); + return Read(buffer, offset, buffer.Length - offset); + } + + /// + /// 将数据读取到中 + /// + /// 输出的数据 + /// 输出数组偏移多少作为起始 + /// 输出的长度 + /// 实际输出的长度 + public int Read(byte[] buffer, int offset, int count) + { + Guard.Requires(buffer != null); + Guard.Requires(offset >= 0); + Guard.Requires(count >= 0); + Guard.Requires((buffer.Length - offset) >= count); + + var readSize = GetCanReadSize(); + if (readSize > count) + { + readSize = count; + } + + if (readSize <= 0) + { + return 0; + } + + var nextReadPos = read + readSize; + + var realReadPos = read & mask; + var realNextReadPos = nextReadPos & mask; + + if (realNextReadPos >= realReadPos) + { + Buffer.BlockCopy(this.buffer, (int)realReadPos, buffer, offset, (int)readSize); + } + else + { + var tail = (int)(capacity - realReadPos); + Buffer.BlockCopy(this.buffer, (int)realReadPos, buffer, offset, tail); + + if (readSize - tail > 0) + { + Buffer.BlockCopy(this.buffer, 0, buffer, offset + tail, (int)readSize - tail); + } + } + + read = nextReadPos; + return (int)readSize; + } + + /// + /// 将数据写入到环型缓冲区 + /// + /// 写入的数据 + /// 实际被写入的长度 + public int Write(byte[] buffer) + { + Guard.Requires(buffer != null); + return Write(buffer, 0, buffer.Length); + } + + /// + /// 将数据写入到环型缓冲区 + /// + /// 写入的数据 + /// 偏移多少数据开始写入 + /// 实际被写入的长度 + public int Write(byte[] buffer, int offset) + { + Guard.Requires(buffer != null); + return Write(buffer, offset, buffer.Length - offset); + } + + /// + /// 将数据写入到环型缓冲区 + /// + /// 写入的数据 + /// 偏移多少数据开始写入 + /// 写入的长度 + /// 实际被写入的长度 + public int Write(byte[] buffer, int offset, int count) + { + Guard.Requires(buffer != null); + Guard.Requires(offset >= 0); + Guard.Requires(count >= 0); + Guard.Requires((buffer.Length - offset) >= count); + + // 得到可以被写入的字节流大小 + var writeSize = GetCanWriteSize(); + if (writeSize > count) + { + writeSize = count; + } + + if (writeSize <= 0) + { + return 0; + } + + // 当前输入结束后下一次开始的写入点 + var nextWritePos = write + writeSize; + + // 通过&运算遮罩快速获得环回中的写入点 + var realWritePos = write & mask; + var realNextWritePos = nextWritePos & mask; + + if (realNextWritePos >= realWritePos) + { + // 不会产生环回,只需要单纯写入 + Buffer.BlockCopy(buffer, offset, this.buffer, (int)realWritePos, (int)writeSize); + } + else + { + // 从写入位置到buffer流尾部的长度 + var tail = (int)(capacity - realWritePos); + Buffer.BlockCopy(buffer, offset, this.buffer, (int)realWritePos, tail); + + if ((writeSize - tail) > 0) + { + Buffer.BlockCopy(buffer, offset + tail, this.buffer, 0, (int)writeSize - tail); + } + } + + write = nextWritePos; + return (int)writeSize; + } + + /// + /// 清空缓冲区中的所有数据 + /// + public void Flush() + { + write = 0; + read = 0; + Array.Clear(buffer, 0, buffer.Length); + } + + /// + /// 释放 + /// + public void Dispose() + { + Flush(); + } + + /// + /// 获取可以被读取的字节流大小 + /// + /// + private long GetCanReadSize() + { + return write - read; + } + + /// + /// 得到可以被写入的字节流大小 + /// + private long GetCanWriteSize() + { + return Math.Max(0, capacity - GetCanReadSize()); + } + + /// + /// 计算规定值最近的二的次幂的容量 + /// + /// 规定值值 + /// 容量 + private static int GetPrime(int min) + { + min = Math.Max(0, min); + + for (var i = 2; i < int.MaxValue; i = i << 1) + { + if (i >= min) + { + return i; + } + } + + throw new RuntimeException("Can not get prime"); + } + } +} From 873c98c950f02453f3787e836da1b8f22c76b339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E5=96=B5=E5=A4=A7=E4=BA=BA?= Date: Sat, 31 Mar 2018 15:43:34 +0800 Subject: [PATCH 21/21] ring buffer add unit test --- .../CatLib.Core.Tests.csproj | 1 + .../Support/RingBuffer/RingBufferTests.cs | 241 ++++++++++++++++++ .../Support/RingBuffer/RingBuffer.cs | 129 ++++++++-- 3 files changed, 344 insertions(+), 27 deletions(-) create mode 100644 src/CatLib.Core.Tests/Support/RingBuffer/RingBufferTests.cs diff --git a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj index e3f89af..fa20fec 100644 --- a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj +++ b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj @@ -49,6 +49,7 @@ + diff --git a/src/CatLib.Core.Tests/Support/RingBuffer/RingBufferTests.cs b/src/CatLib.Core.Tests/Support/RingBuffer/RingBufferTests.cs new file mode 100644 index 0000000..4f07b96 --- /dev/null +++ b/src/CatLib.Core.Tests/Support/RingBuffer/RingBufferTests.cs @@ -0,0 +1,241 @@ +/* + * This file is part of the CatLib package. + * + * (c) Yu Bin + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + * + * Document: http://catlib.io/ + */ + +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace CatLib.Tests.Stl +{ + [TestClass] + public class RingBufferTests + { + [TestMethod] + public void TestReadWrite() + { + var ringBuffer = new RingBuffer(); + var buffer = new byte[] { 1, 2, 4, 5 }; + ringBuffer.Write(buffer, 1, 2); + var read = ringBuffer.Read(); + + Assert.AreEqual(2, read.Length); + Assert.AreEqual(2, read[0]); + Assert.AreEqual(4, read[1]); + + ringBuffer = new RingBuffer(); + buffer = new byte[] { 1, 2, 3, 4, 5 }; + ringBuffer.Write(buffer, 2); + buffer = new byte[5]; + var readCount = ringBuffer.Read(buffer, 2); + + Assert.AreEqual(3, readCount); + Assert.AreEqual(0, buffer[0]); + Assert.AreEqual(0, buffer[1]); + Assert.AreEqual(3, buffer[2]); + Assert.AreEqual(4, buffer[3]); + Assert.AreEqual(5, buffer[4]); + } + + [TestMethod] + public void TestCanRead() + { + var ringBuffer = new RingBuffer(); + var buffer = new byte[] { 1, 2, 3, 4, 5 }; + ringBuffer.Write(buffer); + + Assert.AreEqual(true, ringBuffer.CanRead(4)); + Assert.AreEqual(true, ringBuffer.CanRead(5)); + Assert.AreEqual(false, ringBuffer.CanRead(6)); + ringBuffer.Write(buffer); + Assert.AreEqual(true, ringBuffer.CanRead(9)); + Assert.AreEqual(true, ringBuffer.CanRead(10)); + Assert.AreEqual(false, ringBuffer.CanRead(11)); + } + + [TestMethod] + public void TestCanWrite() + { + var ringBuffer = new RingBuffer(12); // 16 cap + Assert.AreEqual(true, ringBuffer.CanWrite(15)); + Assert.AreEqual(true, ringBuffer.CanWrite(16)); + Assert.AreEqual(false, ringBuffer.CanWrite(17)); + + ringBuffer.Write(new byte[] { 1, 2, 3, 4, 5 }); + Assert.AreEqual(true, ringBuffer.CanWrite(10)); + Assert.AreEqual(true, ringBuffer.CanWrite(11)); + Assert.AreEqual(false, ringBuffer.CanWrite(12)); + + ringBuffer.Write(new byte[] { 1, 2, 3, 4, 5 }, 3); + Assert.AreEqual(true, ringBuffer.CanWrite(8)); + Assert.AreEqual(true, ringBuffer.CanWrite(9)); + Assert.AreEqual(false, ringBuffer.CanWrite(10)); + } + + [TestMethod] + public void TestPeek() + { + var ringBuffer = new RingBuffer(12); // 16 cap + var buffer = new byte[] { 1, 2, 3, 4, 5 }; + ringBuffer.Write(buffer); + + Assert.AreEqual(11, ringBuffer.WriteableCapacity); + Assert.AreEqual(5, ringBuffer.ReadableCapacity); + + var data = ringBuffer.Peek(); + Assert.AreEqual(5, data.Length); + Assert.AreEqual(1, data[0]); + Assert.AreEqual(2, data[1]); + Assert.AreEqual(3, data[2]); + Assert.AreEqual(4, data[3]); + Assert.AreEqual(5, data[4]); + + var data2 = new byte[5]; + var read = ringBuffer.Peek(data2, 3); + Assert.AreEqual(2, read); + Assert.AreEqual(5, data2.Length); + Assert.AreEqual(0, data2[0]); + Assert.AreEqual(0, data2[1]); + Assert.AreEqual(0, data2[2]); + Assert.AreEqual(1, data2[3]); + Assert.AreEqual(2, data2[4]); + + // double peek test + data2 = new byte[5]; + read = ringBuffer.Peek(data2); + Assert.AreEqual(5, read); + Assert.AreEqual(5, data2.Length); + Assert.AreEqual(1, data2[0]); + Assert.AreEqual(2, data2[1]); + Assert.AreEqual(3, data2[2]); + Assert.AreEqual(4, data2[3]); + Assert.AreEqual(5, data2[4]); + + Assert.AreEqual(11, ringBuffer.WriteableCapacity); + Assert.AreEqual(5, ringBuffer.ReadableCapacity); + ringBuffer.Read(); + Assert.AreEqual(16, ringBuffer.WriteableCapacity); + Assert.AreEqual(0, ringBuffer.ReadableCapacity); + } + + [TestMethod] + public void TestFullBuffer() + { + var ringBuffer = new RingBuffer(4); // 4 cap + var buffer = new byte[] { 1, 2, 3, 4, 5 }; + + var write = ringBuffer.Write(buffer); + Assert.AreEqual(4, write); + + Assert.AreEqual(0, ringBuffer.WriteableCapacity); + Assert.AreEqual(4, ringBuffer.ReadableCapacity); + + write = ringBuffer.Write(buffer); + Assert.AreEqual(0, write); + + Assert.AreEqual(0, ringBuffer.WriteableCapacity); + Assert.AreEqual(4, ringBuffer.ReadableCapacity); + } + + [TestMethod] + public void TestReadEmptyBuffer() + { + var ringBuffer = new RingBuffer(4); // 4 cap + var read = ringBuffer.Read(); + Assert.AreEqual(0, read.Length); + + var peek = ringBuffer.Peek(); + Assert.AreEqual(0, peek.Length); + + var buffer = new byte[5]; + var r = ringBuffer.Read(buffer, 2); + + Assert.AreEqual(0, r); + } + + [TestMethod] + public void TestOutOffset() + { + var ringBuffer = new RingBuffer(4); // 4 cap + var buffer = new byte[5]; + ExceptionAssert.Throws(() => + { + ringBuffer.Read(buffer, 2, 10); + }); + + ExceptionAssert.Throws(() => + { + ringBuffer.Write(buffer, 2, 10); + }); + } + + [TestMethod] + public void TestGetBuffer() + { + var ringBuffer = new RingBuffer(12); // 16 cap + Assert.AreEqual(16, ringBuffer.GetBuffer().Length); + ringBuffer = new RingBuffer(12, false); // 16 cap + + ExceptionAssert.Throws(() => + { + ringBuffer.GetBuffer(); + }); + } + + [TestMethod] + public void TestBufferReuse() + { + var ringBuffer = new RingBuffer(12); // 16 cap + var data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + ringBuffer.Write(data); + ringBuffer.Read(); + ringBuffer.Write(data); + var read = ringBuffer.Read(); + + Assert.AreEqual(10, read.Length); + Assert.AreEqual(1, read[0]); + Assert.AreEqual(10, read[9]); + } + + [TestMethod] + public void TestGetAsync() + { + var ringBuffer = new RingBuffer(12); // 16 cap + Assert.AreEqual(ringBuffer.SyncRoot, ringBuffer.SyncRoot); + } + + [TestMethod] + public void TestCapacity() + { + var ringBuffer = new RingBuffer(18); // 32 cap + Assert.AreEqual(32, ringBuffer.Capacity); + } + + [TestMethod] + public void TestDispose() + { + var ringBuffer = new RingBuffer(18); // 32 cap + var data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + ringBuffer.Write(data); + ringBuffer.Flush(); + + Assert.AreEqual(0, ringBuffer.ReadableCapacity); + Assert.AreEqual(32, ringBuffer.WriteableCapacity); + + using (ringBuffer = new RingBuffer(18)) + { + data = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + ringBuffer.Write(data); + } + + Assert.AreEqual(0, ringBuffer.ReadableCapacity); + Assert.AreEqual(32, ringBuffer.WriteableCapacity); + } + } +} diff --git a/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs index 933831a..b1dccab 100644 --- a/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs +++ b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs @@ -9,7 +9,7 @@ namespace CatLib /// /// 环型缓冲区 /// - public sealed class RingBufferStream : IDisposable + public sealed class RingBuffer : IDisposable { /// /// 容量 @@ -71,37 +71,29 @@ public object SyncRoot } /// - /// 可以进行读取 + /// 可写容量 /// - public bool CanRead + public int WriteableCapacity { - get { return GetCanReadSize() > 0; } + get { return (int)GetCanWriteSize(); } } /// - /// 是否可以进行写入 + /// 可读容量 /// - public bool CanWrite() + public int ReadableCapacity { - return CanWrite(1); - } - - /// - /// 是否可以进行写入 - /// - /// 指定的长度 - public bool CanWrite(int count) - { - return GetCanWriteSize() >= count; + get { return (int) GetCanReadSize(); } } /// /// 构建一个新的环型缓冲区实例 /// - /// 容量 + /// 容量,将为临近2的次方(向上取) /// 是否可以访问内部数组 - public RingBufferStream(int capacity, bool exposable = true) + public RingBuffer(int capacity = 8192, bool exposable = true) { + Guard.Requires(capacity > 0); buffer = new byte[this.capacity = GetPrime(capacity)]; mask = this.capacity - 1; write = 0; @@ -109,6 +101,26 @@ public RingBufferStream(int capacity, bool exposable = true) this.exposable = exposable; } + /// + /// 是否可以进行读取 + /// + /// 指定的长度 + public bool CanRead(int count = 1) + { + Guard.Requires(capacity > 0); + return GetCanReadSize() >= count; + } + + /// + /// 是否可以进行写入 + /// + /// 指定的长度 + public bool CanWrite(int count = 1) + { + Guard.Requires(capacity > 0); + return GetCanWriteSize() >= count; + } + /// /// 获取环型缓冲区的原始数组 /// @@ -128,15 +140,14 @@ public byte[] GetBuffer() /// 可以读取的数据 public byte[] Read() { - var readSize = GetCanReadSize(); - if (readSize <= 0) + var buffer = MakeReadableBuffer(); + if (buffer == null) { - return null; + return new byte[0]; } - var result = new byte[readSize]; - Read(result); - return result; + Read(buffer); + return buffer; } /// @@ -170,6 +181,59 @@ public int Read(byte[] buffer, int offset) /// 输出的长度 /// 实际输出的长度 public int Read(byte[] buffer, int offset, int count) + { + var readSize = Peek(buffer, offset, count); + read += readSize; + return readSize; + } + + /// + /// 将环型缓冲区的数据全部返回,但是不前移读取位置 + /// + /// 实际输出的长度 + public byte[] Peek() + { + var buffer = MakeReadableBuffer(); + if (buffer == null) + { + return new byte[0]; + } + + Peek(buffer, 0, buffer.Length); + return buffer; + } + + /// + /// 将环型缓冲区的数据读取到中,但是不前移读取位置 + /// + /// 输出的数据 + /// 实际输出的长度 + public int Peek(byte[] buffer) + { + Guard.Requires(buffer != null); + return Peek(buffer, 0, buffer.Length); + } + + /// + /// 将环型缓冲区的数据读取到中,但是不前移读取位置 + /// + /// 输出的数据 + /// 输出数组偏移多少作为起始 + /// 实际输出的长度 + public int Peek(byte[] buffer, int offset) + { + Guard.Requires(buffer != null); + return Peek(buffer, offset, buffer.Length - offset); + } + + /// + /// 将环型缓冲区的数据读取到中,但是不前移读取位置 + /// + /// 输出的数据 + /// 输出数组偏移多少作为起始 + /// 输出的长度 + /// 实际输出的长度 + public int Peek(byte[] buffer, int offset, int count) { Guard.Requires(buffer != null); Guard.Requires(offset >= 0); @@ -207,7 +271,6 @@ public int Read(byte[] buffer, int offset, int count) } } - read = nextReadPos; return (int)readSize; } @@ -323,6 +386,16 @@ private long GetCanWriteSize() return Math.Max(0, capacity - GetCanReadSize()); } + /// + /// 获取当前可读的buffer + /// + /// 可以被读取的buffer + private byte[] MakeReadableBuffer() + { + var readSize = GetCanReadSize(); + return readSize <= 0 ? null : new byte[readSize]; + } + /// /// 计算规定值最近的二的次幂的容量 /// @@ -332,15 +405,17 @@ private static int GetPrime(int min) { min = Math.Max(0, min); + var result = 8192; for (var i = 2; i < int.MaxValue; i = i << 1) { if (i >= min) { - return i; + result = i; + break; } } - throw new RuntimeException("Can not get prime"); + return result; } } }