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/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
```
**直接下载发布版本**
diff --git a/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj b/src/CatLib.Core.NetStandard/CatLib.Core.NetStandard.csproj
index 6c30e6f..cf208fd 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
@@ -58,11 +58,16 @@
+
+
+
+
+
@@ -84,7 +89,6 @@
-
@@ -96,6 +100,7 @@
+
@@ -120,7 +125,7 @@
-
+
@@ -129,6 +134,7 @@
+
diff --git a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
index b01e6aa..fa20fec 100644
--- a/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
+++ b/src/CatLib.Core.Tests/CatLib.Core.Tests.csproj
@@ -36,6 +36,7 @@
+
@@ -48,6 +49,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..1440137
--- /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.Listen("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.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/Container/ContainerHelperTests.cs b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs
index 727ce14..918c26e 100644
--- a/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs
+++ b/src/CatLib.Core.Tests/Support/Container/ContainerHelperTests.cs
@@ -315,9 +315,33 @@ 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[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);
+
+ 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, 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.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.Tests/Support/Dispatcher/DispatcherTests.cs b/src/CatLib.Core.Tests/Support/Dispatcher/DispatcherTests.cs
index 34cee8d..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()
{
@@ -177,6 +191,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.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.Tests/Support/SortSet/SortSetTests.cs b/src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs
index 3786e6f..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
@@ -21,6 +22,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
/// 事件名称
+ /// 事件调用目标
/// 事件处理方法
/// 事件对象
- public static IEvent On(string eventName, Action method)
+ public static IEvent On(string eventName, object target, string method = null)
{
- return Handler.On(eventName, method);
+ return Handler.On(eventName, target, method);
}
///
/// 注册一个事件监听器
///
/// 事件名称
- /// 事件调用目标
/// 事件处理方法
+ /// 事件分组
/// 事件对象
- 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);
}
///
@@ -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,23 @@ public static IEvent On(string eventName, Action method)
///
/// 事件名称
/// 事件处理方法
+ /// 事件分组
+ /// 事件对象
+ public static IEvent On(string eventName, Action method, object group = null)
+ {
+ return Handler.On(eventName, method, group);
+ }
+
+ ///
+ /// 注册一个事件监听器
+ ///
+ /// 事件名称
+ /// 事件调用方法
+ /// 事件分组
/// 事件对象
- public static IEvent On(string eventName, Action method)
+ public static IEvent Listen(string eventName, Func execution, object group = null)
{
- return Handler.On(eventName, method);
+ return Handler.On(eventName, execution, group);
}
///
@@ -274,10 +291,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 +303,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 +315,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 +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);
}
///
@@ -318,10 +339,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);
}
///
@@ -1049,10 +1071,11 @@ public static bool Release()
/// 根据实例对象释放静态化实例
///
/// 需要释放静态化实例对象
- /// 只要有一个没有释放成功那么返回false
- public static bool Release(params object[] instances)
+ /// 以相反的顺序释放实例
+ /// 只要有一个没有释放成功那么返回false,为没有释放掉的实例
+ public static bool Release(ref object[] instances, bool reverse = true)
{
- return Handler.Release(instances);
+ return Handler.Release(ref instances, reverse);
}
///
diff --git a/src/CatLib.Core/CatLib/Application.cs b/src/CatLib.Core/CatLib/Application.cs
index 1d2f3b6..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框架
///
@@ -345,12 +354,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 +441,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 51%
rename from src/CatLib.Core/Support/Events/DispatcherExtend.cs
rename to src/CatLib.Core/CatLib/Events/DispatcherExtend.cs
index c20d675..c708155 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), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+ 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,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.On(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -54,11 +87,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.On(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -67,11 +108,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.On(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -80,11 +129,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.On(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -93,11 +150,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.On(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -106,11 +171,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.Listen(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -119,11 +192,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.Listen(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -132,11 +213,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.Listen(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -145,11 +234,19 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.Listen(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ return dispatcher.On(eventName, method.Target, method.Method, group);
+#endif
}
///
@@ -158,11 +255,38 @@ 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);
+#if CATLIB_PERFORMANCE
+ var globalDispatcher = ToGlobalDispatcher(dispatcher);
+ return globalDispatcher != null
+ ? globalDispatcher.Listen(eventName, method, group)
+ : dispatcher.On(eventName, method.Target, method.Method, group);
+#else
+ 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
new file mode 100644
index 0000000..4dd3cc0
--- /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, IGlobalDispatcher
+ {
+ ///
+ /// 依赖解决器
+ ///
+ 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/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; }
+ }
+}
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();
+ }
+}
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/Container/Container.cs b/src/CatLib.Core/Support/Container/Container.cs
index 23906b8..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 + "]";
+ }
+
///
/// 生成一个未能解决基本类型的异常
///
@@ -1391,13 +1417,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 +1471,10 @@ protected virtual object[] GetDependencies(Bindable makeServiceBindData, Paramet
throw new UnresolvableException(error);
}
- results.Add(param);
+ results[i] = param;
}
- return results.ToArray();
+ return results;
}
///
diff --git a/src/CatLib.Core/Support/Container/ContainerExtend.cs b/src/CatLib.Core/Support/Container/ContainerExtend.cs
index 6a7d5ce..d448391 100644
--- a/src/CatLib.Core/Support/Container/ContainerExtend.cs
+++ b/src/CatLib.Core/Support/Container/ContainerExtend.cs
@@ -493,29 +493,43 @@ 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, bool reverse = true)
{
- var released = true;
- if (instances == null)
+ if (instances == null || instances.Length <= 0)
{
- return released;
+ return true;
}
- foreach (var instance in instances)
+ if (reverse)
+ {
+ Array.Reverse(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);
+
+ if (reverse && errorIndex > 0)
+ {
+ Array.Reverse(instances);
+ }
+
+ return errorIndex <= 0;
}
///
diff --git a/src/CatLib.Core/Support/Events/Dispatcher.cs b/src/CatLib.Core/Support/Events/Dispatcher.cs
index 64424f9..e123372 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)
{
@@ -209,7 +187,6 @@ public void Off(object target)
{
DismissEventName(eventName);
}
- 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;
+ }
+
///
/// 调度事件
///
@@ -360,7 +346,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 +366,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 +393,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 +401,7 @@ private void ForgetListen(IEvent target)
events.Remove(target);
if (events.Count <= 0)
{
- listeners.Remove(target.EventName);
+ listeners.Remove(target.Name);
}
}
@@ -426,7 +412,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 +420,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 +428,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 +439,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 +448,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 +460,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..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
{
@@ -50,10 +49,10 @@ public interface IDispatcher
/// 注册一个事件监听器
///
/// 事件名称
- /// 调用目标
- /// 调用方法
+ /// 事件调用方法
+ /// 事件分组,为Null
则不进行分组
/// 事件对象
- IEvent On(string eventName, object target, MethodInfo method);
+ IEvent On(string eventName, Func execution, object group = null);
///
/// 解除注册的事件监听器
@@ -62,7 +61,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);
diff --git a/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs
new file mode 100644
index 0000000..b1dccab
--- /dev/null
+++ b/src/CatLib.Core/Support/RingBuffer/RingBuffer.cs
@@ -0,0 +1,421 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace CatLib
+{
+ ///
+ /// 环型缓冲区
+ ///
+ public sealed class RingBuffer : 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 int WriteableCapacity
+ {
+ get { return (int)GetCanWriteSize(); }
+ }
+
+ ///
+ /// 可读容量
+ ///
+ public int ReadableCapacity
+ {
+ get { return (int) GetCanReadSize(); }
+ }
+
+ ///
+ /// 构建一个新的环型缓冲区实例
+ ///
+ /// 容量,将为临近2的次方(向上取)
+ /// 是否可以访问内部数组
+ 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;
+ read = 0;
+ 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;
+ }
+
+ ///
+ /// 获取环型缓冲区的原始数组
+ ///
+ /// 原始数组
+ public byte[] GetBuffer()
+ {
+ if (!exposable)
+ {
+ throw new UnauthorizedAccessException("Unable to access original array");
+ }
+ return buffer;
+ }
+
+ ///
+ /// 将可以读取的数据全部返回
+ ///
+ /// 可以读取的数据
+ public byte[] Read()
+ {
+ var buffer = MakeReadableBuffer();
+ if (buffer == null)
+ {
+ return new byte[0];
+ }
+
+ Read(buffer);
+ return buffer;
+ }
+
+ ///
+ /// 将数据读取到中
+ ///
+ /// 输出的数据
+ /// 实际输出的长度
+ 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)
+ {
+ 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);
+ 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);
+ }
+ }
+
+ 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());
+ }
+
+ ///
+ /// 获取当前可读的buffer
+ ///
+ /// 可以被读取的buffer
+ private byte[] MakeReadableBuffer()
+ {
+ var readSize = GetCanReadSize();
+ return readSize <= 0 ? null : new byte[readSize];
+ }
+
+ ///
+ /// 计算规定值最近的二的次幂的容量
+ ///
+ /// 规定值值
+ /// 容量
+ 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)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+ }
+ }
+}
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
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;
}
///