From 1b1227fb7c5ff190632f3595f439266ee3688237 Mon Sep 17 00:00:00 2001
From: yhh <359807859@qq.com>
Date: Thu, 23 Aug 2018 14:25:28 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BF=AB=E6=8D=B7=E5=AE=B9?=
=?UTF-8?q?=E5=99=A8=20=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97=E5=BC=95?=
=?UTF-8?q?=E6=93=8E=20=E7=BC=96=E8=BE=91=E5=99=A8=E9=A2=84=E7=95=99?=
=?UTF-8?q?=E8=B7=A8=E5=B9=B3=E5=8F=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CLEditor.AssetEngine.csproj | 46 ++
.../Properties/AssemblyInfo.cs | 36 ++
CLEditor.Core/AccessorMetadata.cs | 21 +
CLEditor.Core/CLEditor.Core.csproj | 27 +-
CLEditor.Core/ComponentBase.cs | 57 +++
CLEditor.Core/DataMemberIgnoreAttribute.cs | 13 +
CLEditor.Core/DefaultValueMetadata.cs | 26 ++
.../Diagnostics/ConsoleLogListener.cs | 162 +++++++
CLEditor.Core/Diagnostics/ConsoleLogMode.cs | 22 +
CLEditor.Core/Diagnostics/GlobalLogger.cs | 83 ++++
CLEditor.Core/Diagnostics/LogListener.cs | 87 ++++
CLEditor.Core/Diagnostics/Logger.Extension.cs | 133 ++++++
CLEditor.Core/Diagnostics/Logger.cs | 23 +-
CLEditor.Core/DisposeBase.cs | 66 +++
CLEditor.Core/ICollectorHolder.cs | 13 +
CLEditor.Core/IComponent.cs | 13 +
CLEditor.Core/IReferencable.cs | 24 +
CLEditor.Core/ObjectCollector.cs | 57 +++
CLEditor.Core/ObjectInvalidationMetadata.cs | 7 +
CLEditor.Core/Platform.cs | 70 +++
CLEditor.Core/PlatformType.cs | 47 ++
CLEditor.Core/PropertyContainer.cs | 432 ++++++++++++++++++
CLEditor.Core/PropertyKey.cs | 77 ++++
CLEditor.Core/PropertyKeyMetadata.cs | 7 +
.../ReferenceCountingExtensions.cs | 20 +
.../Serialization/DataSerializerAttribute.cs | 25 +
.../DataSerializerGenericMode.cs | 19 +
CLEditor.Core/Utilities.cs | 20 +
CLEditor.Core/ValidateValueMetadata.cs | 7 +
CLEditor.sln | 31 ++
CLEngine/CGame.cs | 28 ++
CLEngine/CLEngine.csproj | 59 +++
CLEngine/Properties/AssemblyInfo.cs | 36 ++
CLEngine/packages.config | 4 +
README.md | 34 ++
35 files changed, 1830 insertions(+), 2 deletions(-)
create mode 100644 CLEditor.AssetEngine/CLEditor.AssetEngine.csproj
create mode 100644 CLEditor.AssetEngine/Properties/AssemblyInfo.cs
create mode 100644 CLEditor.Core/AccessorMetadata.cs
create mode 100644 CLEditor.Core/ComponentBase.cs
create mode 100644 CLEditor.Core/DataMemberIgnoreAttribute.cs
create mode 100644 CLEditor.Core/DefaultValueMetadata.cs
create mode 100644 CLEditor.Core/Diagnostics/ConsoleLogListener.cs
create mode 100644 CLEditor.Core/Diagnostics/ConsoleLogMode.cs
create mode 100644 CLEditor.Core/Diagnostics/GlobalLogger.cs
create mode 100644 CLEditor.Core/Diagnostics/LogListener.cs
create mode 100644 CLEditor.Core/Diagnostics/Logger.Extension.cs
create mode 100644 CLEditor.Core/DisposeBase.cs
create mode 100644 CLEditor.Core/ICollectorHolder.cs
create mode 100644 CLEditor.Core/IComponent.cs
create mode 100644 CLEditor.Core/IReferencable.cs
create mode 100644 CLEditor.Core/ObjectCollector.cs
create mode 100644 CLEditor.Core/ObjectInvalidationMetadata.cs
create mode 100644 CLEditor.Core/Platform.cs
create mode 100644 CLEditor.Core/PlatformType.cs
create mode 100644 CLEditor.Core/PropertyContainer.cs
create mode 100644 CLEditor.Core/PropertyKey.cs
create mode 100644 CLEditor.Core/PropertyKeyMetadata.cs
create mode 100644 CLEditor.Core/ReferenceCounting/ReferenceCountingExtensions.cs
create mode 100644 CLEditor.Core/Serialization/DataSerializerAttribute.cs
create mode 100644 CLEditor.Core/Serialization/DataSerializerGenericMode.cs
create mode 100644 CLEditor.Core/Utilities.cs
create mode 100644 CLEditor.Core/ValidateValueMetadata.cs
create mode 100644 CLEngine/CGame.cs
create mode 100644 CLEngine/CLEngine.csproj
create mode 100644 CLEngine/Properties/AssemblyInfo.cs
create mode 100644 CLEngine/packages.config
diff --git a/CLEditor.AssetEngine/CLEditor.AssetEngine.csproj b/CLEditor.AssetEngine/CLEditor.AssetEngine.csproj
new file mode 100644
index 0000000..3828d66
--- /dev/null
+++ b/CLEditor.AssetEngine/CLEditor.AssetEngine.csproj
@@ -0,0 +1,46 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FE171BF2-9210-4A24-BCE4-BDB95E6202F5}
+ Library
+ Properties
+ CLEditor.AssetEngine
+ CLEditor.AssetEngine
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CLEditor.AssetEngine/Properties/AssemblyInfo.cs b/CLEditor.AssetEngine/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..07cc832
--- /dev/null
+++ b/CLEditor.AssetEngine/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("CLEditor.AssetEngine")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("CLEditor.AssetEngine")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("fe171bf2-9210-4a24-bce4-bdb95e6202f5")]
+
+// 程序集的版本信息由下列四个值组成:
+//
+// 主版本
+// 次版本
+// 生成号
+// 修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+//通过使用 "*",如下所示:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/CLEditor.Core/AccessorMetadata.cs b/CLEditor.Core/AccessorMetadata.cs
new file mode 100644
index 0000000..3c228ba
--- /dev/null
+++ b/CLEditor.Core/AccessorMetadata.cs
@@ -0,0 +1,21 @@
+namespace CLEditor.Core
+{
+ public class AccessorMetadata : PropertyKeyMetadata
+ {
+ public delegate object GetterDelegate(ref PropertyContainer propertyContainer);
+ public delegate void SetterDelegate(ref PropertyContainer propertyContainer, object value);
+
+ private GetterDelegate getter;
+ private SetterDelegate setter;
+
+ public object GetValue(ref PropertyContainer obj)
+ {
+ return getter(ref obj);
+ }
+
+ public void SetValue(ref PropertyContainer obj, object value)
+ {
+ setter(ref obj, value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/CLEditor.Core.csproj b/CLEditor.Core/CLEditor.Core.csproj
index 409252a..e8f02ab 100644
--- a/CLEditor.Core/CLEditor.Core.csproj
+++ b/CLEditor.Core/CLEditor.Core.csproj
@@ -18,7 +18,7 @@
full
false
bin\Debug\
- DEBUG;TRACE
+ TRACE;DEBUG;C_PLATFORM_WINDOWS_DESKTOP
prompt
4
true
@@ -61,27 +61,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CLEditor.Core/ComponentBase.cs b/CLEditor.Core/ComponentBase.cs
new file mode 100644
index 0000000..393a4fd
--- /dev/null
+++ b/CLEditor.Core/ComponentBase.cs
@@ -0,0 +1,57 @@
+namespace CLEditor.Core
+{
+ ///
+ /// 框架组件的基类
+ ///
+ [DataContract]
+ public abstract class ComponentBase : DisposeBase, IComponent, ICollectorHolder
+ {
+ private string name;
+ private ObjectCollector collector;
+
+ ///
+ /// 获取或设置此组件的名称
+ ///
+ public virtual string Name
+ {
+ get { return name; }
+ set
+ {
+ if (value == name)
+ {
+ return;
+ }
+
+ name = value;
+
+ OnNameChanged();
+ }
+ }
+
+ ///
+ /// 获取此组件的附加属性
+ ///
+ [DataMemberIgnore]
+ public PropertyContainer Tags;
+
+ public ComponentBase(string name)
+ {
+ collector = new ObjectCollector();
+ Tags = new PropertyContainer(this);
+ Name = name ?? GetType().Name;
+ }
+
+ public ObjectCollector Collector
+ {
+ get
+ {
+ collector.EnsureValid();
+ return collector;
+ }
+ }
+
+ protected virtual void OnNameChanged()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/DataMemberIgnoreAttribute.cs b/CLEditor.Core/DataMemberIgnoreAttribute.cs
new file mode 100644
index 0000000..89f5841
--- /dev/null
+++ b/CLEditor.Core/DataMemberIgnoreAttribute.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace CLEditor.Core
+{
+ ///
+ /// 在属性或字段上指定时,在序列化/反序列化时不会使用它
+ ///
+ [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, Inherited = false)]
+ public class DataMemberIgnoreAttribute : Attribute
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/DefaultValueMetadata.cs b/CLEditor.Core/DefaultValueMetadata.cs
new file mode 100644
index 0000000..a9cac5d
--- /dev/null
+++ b/CLEditor.Core/DefaultValueMetadata.cs
@@ -0,0 +1,26 @@
+namespace CLEditor.Core
+{
+ ///
+ /// 可以重载的抽象类
+ ///
+ public abstract class DefaultValueMetadata : PropertyKeyMetadata
+ {
+ ///
+ /// 获取外部属性的默认值,并指定是否应保留此默认值
+ ///
+ ///
+ ///
+ public abstract object GetDefaultValue(ref PropertyContainer obj);
+ ///
+ /// 获取或设置属性更新回调
+ ///
+ public PropertyContainer.PropertyUpdatedDelegate PropertyUpdateCallback { get; set; }
+ ///
+ /// 获取一个值,该值指示是否保留此值
+ ///
+ public virtual bool KeepValue
+ {
+ get { return false; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/ConsoleLogListener.cs b/CLEditor.Core/Diagnostics/ConsoleLogListener.cs
new file mode 100644
index 0000000..fa60e4c
--- /dev/null
+++ b/CLEditor.Core/Diagnostics/ConsoleLogListener.cs
@@ -0,0 +1,162 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using CLEditor.Core.Annotations;
+using Microsoft.Win32.SafeHandles;
+
+namespace CLEditor.Core.Diagnostics
+{
+ ///
+ /// 实现将其输出重定向到默认的OS控制台
+ ///
+ public class ConsoleLogListener : LogListener
+ {
+#if C_PLATFORM_WINDOWS_DESKTOP
+ private bool isConsoleActive;
+#endif
+ public static void ShowConsole()
+ {
+ var handle = GetConsoleWindow();
+ var outputRedirected = IsHandleRedirected((IntPtr)StdOutConsoleHandle);
+
+ if (outputRedirected)
+ {
+ var originalStream = Console.OpenStandardOutput();
+
+ FreeConsole();
+ AllocConsole();
+
+ var outputStream = Console.OpenStandardOutput();
+ if (originalStream != null)
+ {
+ outputStream = new DualStream(originalStream, outputStream);
+ }
+
+ TextWriter writer = new StreamWriter(outputStream) { AutoFlush = true };
+ Console.SetOut(writer);
+ }
+ else if (handle != IntPtr.Zero)
+ {
+ const int SW_SHOW = 5;
+ ShowWindow(handle, SW_SHOW);
+ }
+ }
+
+ private static bool IsHandleRedirected(IntPtr ioHandle)
+ {
+ if ((GetFileType(new SafeFileHandle(ioHandle, false)) & 2) != 2)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// 获取或设置此侦听器处理的最小日志级别
+ ///
+ public LogMessageType LogLevel { get; set; }
+ ///
+ /// 获取或设置日志模式
+ ///
+ public ConsoleLogMode LogMode { get; set; }
+
+ protected override void OnLog([NotNull] ILogMessage logMessage)
+ {
+ if (!Debugger.IsAttached && (logMessage.Type < LogLevel || LogMode == ConsoleLogMode.None
+ || !(LogMode == ConsoleLogMode.Auto &&
+ Platform.IsRunningDebugAssembly) &&
+ LogMode != ConsoleLogMode.Always))
+ {
+ return;
+ }
+ }
+
+#if C_PLATFORM_WINDOWS_DESKTOP
+ private const int StdOutConsoleHandle = -11;
+
+ public static void HideConsole()
+ {
+ var handle = GetConsoleWindow();
+ const int SW_HIDE = 0;
+ ShowWindow(handle, SW_HIDE);
+ }
+
+ private class DualStream : Stream
+ {
+ private readonly Stream stream1;
+ private readonly Stream stream2;
+
+ public DualStream(Stream stream1, Stream stream2)
+ {
+ this.stream1 = stream1;
+ this.stream2 = stream2;
+ }
+
+ public override void Flush()
+ {
+ stream1.Flush();
+ stream2.Flush();
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ stream1.Write(buffer, offset, count);
+ stream2.Write(buffer, offset, count);
+ }
+
+ public override bool CanRead => false;
+ public override bool CanSeek => false;
+ public override bool CanWrite => false;
+ public override long Length { get; }
+ public override long Position { get; set; }
+ }
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GetConsoleWindow();
+ [DllImport("kernel32.dll")]
+ private static extern int GetFileType(SafeFileHandle handle);
+ [DllImport("user32.dll")]
+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool FreeConsole();
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool AllocConsole();
+ [DllImport("kernel32", SetLastError = true)]
+ private static extern bool AttachConsole(int dwProcessId);
+
+ private void EnsureConsole()
+ {
+ if (isConsoleActive || !Platform.IsWindowsDesktop)
+ {
+ return;
+ }
+
+ var attackedToConsole = AttachConsole(-1);
+ if (!attackedToConsole)
+ {
+ ShowConsole();
+ }
+
+ isConsoleActive = true;
+ }
+#endif
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/ConsoleLogMode.cs b/CLEditor.Core/Diagnostics/ConsoleLogMode.cs
new file mode 100644
index 0000000..b06d113
--- /dev/null
+++ b/CLEditor.Core/Diagnostics/ConsoleLogMode.cs
@@ -0,0 +1,22 @@
+namespace CLEditor.Core.Diagnostics
+{
+ ///
+ /// 定义控制台的打开方式
+ ///
+ public enum ConsoleLogMode
+ {
+ ///
+ /// 控制台应仅在调试中可见,如果有消息,则不可见
+ ///
+ Auto,
+ Default = Auto,
+ ///
+ /// 控制台不可见
+ ///
+ None,
+ ///
+ /// 控制台始终可见
+ ///
+ Always,
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/GlobalLogger.cs b/CLEditor.Core/Diagnostics/GlobalLogger.cs
new file mode 100644
index 0000000..c303f42
--- /dev/null
+++ b/CLEditor.Core/Diagnostics/GlobalLogger.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using CLEditor.Core.Annotations;
+
+namespace CLEditor.Core.Diagnostics
+{
+ ///
+ /// 一种记录器,它将消息重定向到全局处理程序并处理实例化的MapModuleNameToLogger
+ ///
+ public sealed class GlobalLogger : Logger
+ {
+ ///
+ /// 默认情况下,GlobalLogger的最低级别为info
+ ///
+ public const LogMessageType MinimumLevel = LogMessageType.Info;
+ ///
+ /// 映射所有实例化的记录器
+ /// 将模块名称映射到记录器
+ ///
+ private static readonly Dictionary MapModuleNameToLogger = new Dictionary();
+
+ public delegate void MessageFilterDelegate(ref ILogMessage logMessage);
+ ///
+ /// 记录消息时发生
+ ///
+ public static event Action GlobalMessageLogged;
+ ///
+ /// 在记录消息之前发生
+ ///
+ public static event MessageFilterDelegate GlobalMessageFilter;
+
+ private GlobalLogger(string module)
+ {
+ Module = module;
+ }
+
+ public static Logger GetLogger([NotNull] string module)
+ {
+ if (module == null)
+ throw new ArgumentNullException(nameof(module));
+
+ Logger logger;
+ lock (MapModuleNameToLogger)
+ {
+ if (!MapModuleNameToLogger.TryGetValue(module, out logger))
+ {
+ logger = new GlobalLogger(module);
+ logger.ActivateLog(MinimumLevel);
+ MapModuleNameToLogger.Add(module, logger);
+ }
+ }
+ return logger;
+ }
+
+ ///
+ /// 使用指定的操作激活所有记录器的日志
+ ///
+ ///
+ public static void ActivateLog([NotNull] Action activator)
+ {
+ if (activator == null)
+ throw new ArgumentNullException(nameof(activator));
+
+ foreach (var logger in MapModuleNameToLogger.Values)
+ activator(logger);
+ }
+
+ protected override void LogRaw(ILogMessage logMessage)
+ {
+ var filterHandler = GlobalMessageFilter;
+ if (filterHandler != null)
+ {
+ filterHandler(ref logMessage);
+ if (logMessage == null)
+ {
+ return;
+ }
+ }
+
+ GlobalMessageLogged?.Invoke(logMessage);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/LogListener.cs b/CLEditor.Core/Diagnostics/LogListener.cs
new file mode 100644
index 0000000..544c232
--- /dev/null
+++ b/CLEditor.Core/Diagnostics/LogListener.cs
@@ -0,0 +1,87 @@
+using System;
+using CLEditor.Core.Annotations;
+
+namespace CLEditor.Core.Diagnostics
+{
+ ///
+ /// 实现日志侦听器的基类
+ ///
+ public abstract class LogListener : IDisposable
+ {
+ ///
+ /// 获取日志消息计数
+ ///
+ public int LogMessageCount { get; private set; }
+
+ protected LogListener()
+ {
+ LogCountFlushLimit = 1;
+ TextFormatter = msg => msg.ToString();
+ }
+
+ public Func TextFormatter { get; set; }
+
+ ///
+ /// 获取或设置日志计数刷新限制。 每条消息都有默认值
+ ///
+ public int LogCountFlushLimit
+ {
+ get { return LogCountFlushLimit; }
+ set
+ {
+ if (value <= 0)
+ {
+ throw new ArgumentException("值必须大于0");
+ }
+
+ LogCountFlushLimit = value;
+ }
+ }
+
+ ///
+ /// 执行与释放,释放或重置非托管资源相关的应用程序定义的任务
+ ///
+ public virtual void Dispose()
+ {
+ }
+
+ ///
+ /// 发生日志时调用
+ ///
+ ///
+ protected abstract void OnLog(ILogMessage logMessage);
+
+ [NotNull]
+ public static implicit operator Action([NotNull] LogListener logListener)
+ {
+ return logListener.OnLogInternal;
+ }
+
+ ///
+ /// 刷新日志,方法在子类中实现
+ ///
+ protected virtual void Flush()
+ {
+ }
+
+ ///
+ /// 返回一个布尔值,指示是否应刷新日志
+ ///
+ ///
+ ///
+ protected virtual bool ShouldFlush([NotNull] ILogMessage logMessage)
+ {
+ return (logMessage.Type > LogMessageType.Info) || (LogMessageCount % LogCountFlushLimit) == 0;
+ }
+
+ private void OnLogInternal([NotNull] ILogMessage logMessage)
+ {
+ OnLog(logMessage);
+ LogMessageCount++;
+ if (ShouldFlush(logMessage))
+ {
+ Flush();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/Logger.Extension.cs b/CLEditor.Core/Diagnostics/Logger.Extension.cs
new file mode 100644
index 0000000..a5c0af9
--- /dev/null
+++ b/CLEditor.Core/Diagnostics/Logger.Extension.cs
@@ -0,0 +1,133 @@
+using System;
+
+namespace CLEditor.Core.Diagnostics
+{
+ public abstract partial class Logger
+ {
+ ///
+ /// 使用异常记录指定的详细消息
+ ///
+ /// 详细消息
+ /// 使用消息记录的异常
+ /// 有关Caller的信息。 默认值为null,否则使用
+ public void Verbose(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Verbose, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的详细消息
+ ///
+ /// 详细消息
+ /// 有关Caller的信息。 默认值为null,否则使用
+ public void Verbose(string message, CallerInfo callerInfo = null)
+ {
+ Verbose(message, null, callerInfo);
+ }
+
+ ///
+ /// 记录指定的调试消息并发生异常
+ ///
+ ///
+ ///
+ ///
+ public void Debug(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Debug, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的调试消息
+ ///
+ ///
+ ///
+ public void Debug(string message, CallerInfo callerInfo = null)
+ {
+ Debug(message, null, callerInfo);
+ }
+
+ ///
+ /// 记录指定的信息消息,但有异常
+ ///
+ ///
+ ///
+ ///
+ public void Info(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Info, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的信息消息
+ ///
+ ///
+ ///
+ public void Info(string message, CallerInfo callerInfo = null)
+ {
+ Info(message, null, callerInfo);
+ }
+
+ ///
+ /// 记录指定的警告消息并发生异常
+ ///
+ ///
+ ///
+ ///
+ public void Warning(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Warning, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的警告消息
+ ///
+ ///
+ ///
+ public void Warning(string message, CallerInfo callerInfo = null)
+ {
+ Warning(message, null, callerInfo);
+ }
+
+ ///
+ /// 记录指定的错误消息,但有异常
+ ///
+ ///
+ ///
+ ///
+ public void Error(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Error, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的错误消息
+ ///
+ ///
+ ///
+ public void Error(string message, CallerInfo callerInfo = null)
+ {
+ Error(message, null, callerInfo);
+ }
+
+ ///
+ /// 使用例外记录指定的致命消息
+ ///
+ ///
+ ///
+ ///
+ public void Fatal(string message, Exception exception, CallerInfo callerInfo = null)
+ {
+ Log(new LogMessage(Module, LogMessageType.Fatal, message, exception, callerInfo));
+ }
+
+ ///
+ /// 记录指定的致命消息
+ ///
+ ///
+ ///
+ public void Fatal(string message, CallerInfo callerInfo = null)
+ {
+ Fatal(message, null, callerInfo);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/Diagnostics/Logger.cs b/CLEditor.Core/Diagnostics/Logger.cs
index ec9a075..075dacf 100644
--- a/CLEditor.Core/Diagnostics/Logger.cs
+++ b/CLEditor.Core/Diagnostics/Logger.cs
@@ -3,7 +3,7 @@ using CLEditor.Core.Annotations;
namespace CLEditor.Core.Diagnostics
{
- public abstract class Logger : ILogger
+ public abstract partial class Logger : ILogger
{
///
/// 获取模块名称。 只读
@@ -43,6 +43,27 @@ namespace CLEditor.Core.Diagnostics
}
}
+ ///
+ /// 激活此记录器的日志
+ /// 在指定范围之外,将禁用日志消息类型
+ ///
+ /// 要记录的最低包含级别
+ /// 要记录的最高包含级别
+ /// 如果设置为 true ,则启用日志,否则为false。 默认为true
+ public void ActivateLog(LogMessageType fromLevel, LogMessageType toLevel = LogMessageType.Fatal, bool enabledFlag = true)
+ {
+ // 从低到高
+ if (fromLevel > toLevel)
+ {
+ var temp = fromLevel;
+ fromLevel = toLevel;
+ toLevel = temp;
+ }
+
+ for (var i = 0; i < EnableTypes.Length; i++)
+ EnableTypes[i] = (i >= (int)fromLevel && i <= (int)toLevel) ? enabledFlag : !enabledFlag;
+ }
+
///
/// 用于记录消息的内部方法。 所有信息,调试,错误......等。
/// 方法正在调用此方法
diff --git a/CLEditor.Core/DisposeBase.cs b/CLEditor.Core/DisposeBase.cs
new file mode 100644
index 0000000..699cd46
--- /dev/null
+++ b/CLEditor.Core/DisposeBase.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Threading;
+using CLEditor.Core.ReferenceCounting;
+
+namespace CLEditor.Core
+{
+ public abstract class DisposeBase : IDisposable, IReferencable
+ {
+ private int counter = 1;
+ ///
+ /// 组件是否已经处理好
+ ///
+ public bool IsDisposed { get; private set; }
+
+ public void Dispose()
+ {
+ if (!IsDisposed)
+ {
+ this.ReleaseInternal();
+ }
+ }
+
+ public int ReferenceCount => counter;
+
+ public int AddReference()
+ {
+ OnAddReference();
+
+ var newCounter = Interlocked.Increment(ref counter);
+ if (newCounter <= 1) throw new InvalidOperationException("无法为已发布的对象添加引用。 AddReference / Release对必须匹配");
+ return newCounter;
+ }
+
+ protected virtual void OnAddReference()
+ {
+ }
+
+ public int Release()
+ {
+ OnReleaseReference();
+
+ var newCounter = Interlocked.Decrement(ref counter);
+ if (newCounter == 0)
+ {
+ Destroy();
+ IsDisposed = true;
+ }
+ else if (newCounter < 0)
+ {
+ throw new InvalidOperationException("无法释放没有活动引用的对象。 AddReference / Release对必须匹配");
+ }
+ return newCounter;
+ }
+
+ protected virtual void OnReleaseReference()
+ {
+ }
+
+ ///
+ /// 处理对象资源
+ ///
+ protected virtual void Destroy()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/ICollectorHolder.cs b/CLEditor.Core/ICollectorHolder.cs
new file mode 100644
index 0000000..31e8992
--- /dev/null
+++ b/CLEditor.Core/ICollectorHolder.cs
@@ -0,0 +1,13 @@
+namespace CLEditor.Core
+{
+ ///
+ /// 接口ICollectorHolder用于可以收集其他实例的实例
+ ///
+ public interface ICollectorHolder
+ {
+ ///
+ /// 获取收集器
+ ///
+ ObjectCollector Collector { get; }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/IComponent.cs b/CLEditor.Core/IComponent.cs
new file mode 100644
index 0000000..8d81a14
--- /dev/null
+++ b/CLEditor.Core/IComponent.cs
@@ -0,0 +1,13 @@
+namespace CLEditor.Core
+{
+ ///
+ /// 所有组件的基本接口
+ ///
+ public interface IComponent : IReferencable
+ {
+ ///
+ /// 获取此组件的名称
+ ///
+ string Name { get; }
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/IReferencable.cs b/CLEditor.Core/IReferencable.cs
new file mode 100644
index 0000000..f608427
--- /dev/null
+++ b/CLEditor.Core/IReferencable.cs
@@ -0,0 +1,24 @@
+namespace CLEditor.Core
+{
+ ///
+ /// 所有可引用对象的基本接口
+ ///
+ public interface IReferencable
+ {
+ ///
+ /// 获取此实例的引用计数
+ ///
+ int ReferenceCount { get; }
+ ///
+ /// 增加此实例的引用计数
+ ///
+ ///
+ int AddReference();
+ ///
+ /// 减少此实例的引用计数
+ /// 当引用计数变为0时,组件应释放/配置依赖项对象
+ ///
+ ///
+ int Release();
+ }
+}
\ No newline at end of file
diff --git a/CLEditor.Core/ObjectCollector.cs b/CLEditor.Core/ObjectCollector.cs
new file mode 100644
index 0000000..6a438e0
--- /dev/null
+++ b/CLEditor.Core/ObjectCollector.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+
+namespace CLEditor.Core
+{
+ public struct ObjectCollector : IDisposable
+ {
+ private List