diff --git a/CLEditor.BuildEngine.Common/Builder.cs b/CLEditor.BuildEngine.Common/Builder.cs new file mode 100644 index 0000000000000000000000000000000000000000..0dc9d7395f9d2284f5041e91b8393ec1971ba812 --- /dev/null +++ b/CLEditor.BuildEngine.Common/Builder.cs @@ -0,0 +1,84 @@ +using CLEditor.Core.Storage; +using System; +using System.Collections.Generic; +using System.Threading; +using CLEditor.Core.Diagnostics; + +namespace CLEditor.BuildEngine.Common +{ + public class Builder : IDisposable + { + public static ObjectDatabase ObjectDatabase { get; private set; } + public List MonitorPipeNames { get; } + private readonly DateTime startTime; + /// + /// 构建配置文件 + /// + private readonly string buildProfile; + /// + /// 索引文件名的磁盘上的名称 + /// + private readonly string indexName; + /// + /// 构建器和命令使用的记录器 + /// + public ILogger Logger { get; } + /// + /// 磁盘上执行构建的路径 + /// + private readonly string buildPath; + /// + /// 构建器的根构建步骤定义要执行的构建 + /// + public ListBuildStep Root { get; private set; } + + private readonly CommandIOMonitor ioMonitor; + /// + /// 要创建的工作线程数 + /// + public int ThreadCount { get; set; } + public Guid BuilderId { get; } + public IDictionary InitialVariables { get; } + + public Builder(ILogger logger, string buildPath, string buildProfile, string indexName) + { + MonitorPipeNames = new List(); + startTime = DateTime.Now; + this.buildProfile = buildProfile; + this.indexName = indexName; + Logger = logger; + this.buildPath = buildPath ?? throw new ArgumentNullException(nameof(buildPath)); + Root = new ListBuildStep(); + ioMonitor = new CommandIOMonitor(Logger); + ThreadCount = Environment.ProcessorCount; + BuilderId = Guid.NewGuid(); + InitialVariables = new Dictionary(); + } + + public static void CloseObjectDatabase() + { + var db = ObjectDatabase; + ObjectDatabase = null; + db?.Dispose(); + } + + public void Dispose() + { + CloseObjectDatabase(); + } + + private class ExecuteContext : IExecuteContext + { + private readonly Builder builder; + + public ExecuteContext(Builder builder) + { + + } + + public CancellationTokenSource CancellationTokenSource { get; } + public ObjectDatabase ResultMap { get; } + public Dictionary Variables { get; } + } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine.Common/CLEditor.BuildEngine.Common.csproj b/CLEditor.BuildEngine.Common/CLEditor.BuildEngine.Common.csproj new file mode 100644 index 0000000000000000000000000000000000000000..00c9bd3a91a48f4e6b8441aa3a1c674589e6e535 --- /dev/null +++ b/CLEditor.BuildEngine.Common/CLEditor.BuildEngine.Common.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE} + Library + Properties + CLEditor.BuildEngine.Common + CLEditor.BuildEngine.Common + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + True + + + + + + + + + + + + + + + + + + + {F49C4C69-3A15-4201-8AA2-29E115A17311} + CLEditor.BuildEngine + + + {A9459A99-39D8-480B-BF14-A7687ECE7DB1} + CLEditor.Core + + + + \ No newline at end of file diff --git a/CLEditor.BuildEngine.Common/IExecuteContext.cs b/CLEditor.BuildEngine.Common/IExecuteContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..31c90235444fd3d26d5718a874e097bb50d35047 --- /dev/null +++ b/CLEditor.BuildEngine.Common/IExecuteContext.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading; +using CLEditor.Core.Diagnostics; +using CLEditor.Core.Storage; + +namespace CLEditor.BuildEngine.Common +{ + public interface IPrepareContext + { + Logger Logger { get; } + } + + public interface IExecuteContext + { + CancellationTokenSource CancellationTokenSource { get; } + ObjectDatabase ResultMap { get; } + Dictionary Variables { get; } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine.Common/Properties/AssemblyInfo.cs b/CLEditor.BuildEngine.Common/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..e5f34afa85fc3e5f1fe7ecc57128b4735bb51f63 --- /dev/null +++ b/CLEditor.BuildEngine.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("CLEditor.BuildEngine.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CLEditor.BuildEngine.Common")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("14e96242-da07-4408-bfd5-ceb6d2fe9cce")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CLEditor.BuildEngine/BuildStep.cs b/CLEditor.BuildEngine/BuildStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..d866e0a0fde8a0f2633b327a5058074ab785da33 --- /dev/null +++ b/CLEditor.BuildEngine/BuildStep.cs @@ -0,0 +1,15 @@ +namespace CLEditor.BuildEngine +{ + public abstract class BuildStep + { + /// + /// 结果的状态 + /// + public ResultStatus Status { get; private set; } + + protected BuildStep(ResultStatus status = ResultStatus.NotProcessed) + { + Status = status; + } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/BuilderContext.cs b/CLEditor.BuildEngine/BuilderContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..c09949c31b3d63d4a84a2680eb375ed2ae57a7ad --- /dev/null +++ b/CLEditor.BuildEngine/BuilderContext.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using CLEditor.Core.Storage; + +namespace CLEditor.BuildEngine +{ + public class BuilderContext + { + internal readonly Dictionary CommandsInProgress = new Dictionary(); + + public BuilderContext() + { + + } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/CLEditor.BuildEngine.csproj b/CLEditor.BuildEngine/CLEditor.BuildEngine.csproj new file mode 100644 index 0000000000000000000000000000000000000000..2ecaaca09c1b87d1a7b17c30975cc6986d77c061 --- /dev/null +++ b/CLEditor.BuildEngine/CLEditor.BuildEngine.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {F49C4C69-3A15-4201-8AA2-29E115A17311} + Library + Properties + CLEditor.BuildEngine + CLEditor.BuildEngine + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + {A9459A99-39D8-480B-BF14-A7687ECE7DB1} + CLEditor.Core + + + + \ No newline at end of file diff --git a/CLEditor.BuildEngine/CommandBuildStep.cs b/CLEditor.BuildEngine/CommandBuildStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..a91570d651408b1a11d1afae00eeb55bebfef158 --- /dev/null +++ b/CLEditor.BuildEngine/CommandBuildStep.cs @@ -0,0 +1,7 @@ +namespace CLEditor.BuildEngine +{ + public class CommandBuildStep : BuildStep + { + + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/CommandIOMonitor.cs b/CLEditor.BuildEngine/CommandIOMonitor.cs new file mode 100644 index 0000000000000000000000000000000000000000..f609cbd627b7fcfcfcf9bc60896c6a1f6e7ff6a3 --- /dev/null +++ b/CLEditor.BuildEngine/CommandIOMonitor.cs @@ -0,0 +1,20 @@ +using System.Diagnostics; +using CLEditor.Core.Diagnostics; + +namespace CLEditor.BuildEngine +{ + /// + /// 此类监视每个BuildStep执行的输入/输出访问,如果对象url是命令的输入和同时运行的另一个命令的输出,则显示错误消息 + /// + public class CommandIOMonitor + { + private readonly ILogger logger; + private readonly Stopwatch stopwatch = new Stopwatch(); + + public CommandIOMonitor(ILogger logger) + { + this.logger = logger; + stopwatch.Start(); + } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/FileVersionStorage.cs b/CLEditor.BuildEngine/FileVersionStorage.cs new file mode 100644 index 0000000000000000000000000000000000000000..9355af336635c966f94c32f9f3280d60ebb34bc7 --- /dev/null +++ b/CLEditor.BuildEngine/FileVersionStorage.cs @@ -0,0 +1,10 @@ +using CLEditor.Core.IO; +using CLEditor.Core.Storage; + +namespace CLEditor.BuildEngine +{ + public class FileVersionStorage : DictionaryStore + { + + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/FileVersionTracker.cs b/CLEditor.BuildEngine/FileVersionTracker.cs new file mode 100644 index 0000000000000000000000000000000000000000..a676758404ad31dccad5d0cfe0f2e6da8d203438 --- /dev/null +++ b/CLEditor.BuildEngine/FileVersionTracker.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using CLEditor.Core; + +namespace CLEditor.BuildEngine +{ + public class FileVersionTracker : IDisposable + { + private readonly FileVersionStorage storage; + + public void Dispose() + { + storage.Dispose(); + } + } + + [DataContract] + public struct FileVersionKey : IEquatable + { + public string Path; + public DateTime LastModifiedDate; + public long FileSize; + + public bool Equals(FileVersionKey other) + { + return string.Equals(Path, other.Path) && LastModifiedDate.Equals(other.LastModifiedDate) && FileSize == other.FileSize; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is FileVersionKey && Equals((FileVersionKey)obj); + } + + public override int GetHashCode() + { + unchecked + { + int hashCode = (Path != null ? Path.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ LastModifiedDate.GetHashCode(); + hashCode = (hashCode * 397) ^ FileSize.GetHashCode(); + return hashCode; + } + } + + public static bool operator ==(FileVersionKey left, FileVersionKey right) + { + return left.Equals(right); + } + + public static bool operator !=(FileVersionKey left, FileVersionKey right) + { + return !left.Equals(right); + } + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/ListBuildStep.cs b/CLEditor.BuildEngine/ListBuildStep.cs new file mode 100644 index 0000000000000000000000000000000000000000..61f68a9550781a7c205a89e94b7a10f4a416d7db --- /dev/null +++ b/CLEditor.BuildEngine/ListBuildStep.cs @@ -0,0 +1,7 @@ +namespace CLEditor.BuildEngine +{ + public class ListBuildStep : BuildStep + { + + } +} \ No newline at end of file diff --git a/CLEditor.BuildEngine/Properties/AssemblyInfo.cs b/CLEditor.BuildEngine/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..c49e6e07ab2a894018cfafc7a9757643121ee13f --- /dev/null +++ b/CLEditor.BuildEngine/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("CLEditor.BuildEngine")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CLEditor.BuildEngine")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("f49c4c69-3a15-4201-8aa2-29e115a17311")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CLEditor.BuildEngine/ResultStatus.cs b/CLEditor.BuildEngine/ResultStatus.cs new file mode 100644 index 0000000000000000000000000000000000000000..60e0958eeb37add03e27e40d21e834eadc6ebffb --- /dev/null +++ b/CLEditor.BuildEngine/ResultStatus.cs @@ -0,0 +1,33 @@ +namespace CLEditor.BuildEngine +{ + /// + /// 命令的状态 + /// + public enum ResultStatus + { + /// + /// 该命令尚未完成 + /// + NotProcessed, + /// + /// 该命令已成功执行 + /// + Successful, + /// + /// 命令执行失败 + /// + Failed, + /// + /// 该命令已启动但已取消,输出未终止 + /// + Cancelled, + /// + /// 如果自上次执行成功后其输入数据未发生变化,则可能无法触发该命令 + /// + NotTriggeredWasSuccessful, + /// + /// 其中一个先决条件命令失败,并且未执行该命令 + /// + NotTriggeredPrerequisiteFailed + } +} \ No newline at end of file diff --git a/CLEditor.Core/Annotations/NotNullAttribute.cs b/CLEditor.Core/Annotations/NotNullAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..659ead8fbc41615666354644ab02159caa6ade48 --- /dev/null +++ b/CLEditor.Core/Annotations/NotNullAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace CLEditor.Core.Annotations +{ + /// + /// 表示标记元素的值永远不会 null. + /// + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | + AttributeTargets.Delegate | AttributeTargets.Field | AttributeTargets.Event | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.GenericParameter)] + public sealed class NotNullAttribute : Attribute + { + + } +} \ No newline at end of file diff --git a/CLEditor.Core/CLEditor.Core.csproj b/CLEditor.Core/CLEditor.Core.csproj index 048e915ded5f65eacaae5760899c29eeef68c197..409252a766c9582f24bdec9c2d81bf5c66d6a636 100644 --- a/CLEditor.Core/CLEditor.Core.csproj +++ b/CLEditor.Core/CLEditor.Core.csproj @@ -23,7 +23,8 @@ 4 true AnyCPU - 5 + + pdbonly @@ -32,7 +33,7 @@ TRACE prompt 4 - 5 + 6 @@ -60,10 +61,27 @@ + + + + + + + + + + + + + + + + + diff --git a/CLEditor.Core/CLEditor.Core.csproj.DotSettings b/CLEditor.Core/CLEditor.Core.csproj.DotSettings new file mode 100644 index 0000000000000000000000000000000000000000..73e96563f9e34c60c0bc9bec2539defeee7989d4 --- /dev/null +++ b/CLEditor.Core/CLEditor.Core.csproj.DotSettings @@ -0,0 +1,2 @@ + + CSharp60 \ No newline at end of file diff --git a/CLEditor.Core/DataContractAttribute.cs b/CLEditor.Core/DataContractAttribute.cs new file mode 100644 index 0000000000000000000000000000000000000000..73283d5e9d9068d55f6136fd2e2c3eadaa9548fd --- /dev/null +++ b/CLEditor.Core/DataContractAttribute.cs @@ -0,0 +1,37 @@ +using System; + +namespace CLEditor.Core +{ + /// + /// 表示可以序列化类 + /// + [AttributeUsage(AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Class, AllowMultiple = false, Inherited = false)] + public class DataContractAttribute : Attribute + { + /// + /// 序列化为文本格式时的类型别名 + /// + private readonly string alias; + + public DataContractAttribute() + { + } + + public DataContractAttribute(string aliasName) + { + this.alias = aliasName; + } + + /// + /// 在序列化为文本格式时获取或设置别名 + /// + public string Alias => alias; + + public bool Inherited { get; set; } + + /// + /// 默认成员模式 + /// + public DataMemberMode DefaultMemberMode { get; set; } = DataMemberMode.Default; + } +} \ No newline at end of file diff --git a/CLEditor.Core/DataMemberMode.cs b/CLEditor.Core/DataMemberMode.cs new file mode 100644 index 0000000000000000000000000000000000000000..f905297108ec2fa0c422d4042c02a15b1a92bb44 --- /dev/null +++ b/CLEditor.Core/DataMemberMode.cs @@ -0,0 +1,33 @@ +namespace CLEditor.Core +{ + /// + /// 指定存储某个类或结构的属性或字段的方式 + /// + public enum DataMemberMode + { + /// + /// 根据字段/属性的类型使用默认模式 + /// + Default, + /// + /// 还原时,通过使用YAML数据中的参数并将其分配给属性/字段来创建新对象。 + /// 当属性/字段可写时,这是默认值 + /// + Assign, + /// + /// 仅对具有类或结构类型的属性/字段有效。 + /// 恢复后,不会重新创建整个类或结构,而是独立地恢复成员。 + /// 当属性/字段不可写时,这是默认值 + /// + Content, + /// + /// 仅对具有某种值类型的数组类型的属性/字段有效。 + /// 数组的内容以base64样式编码的二进制格式存储 + /// + Binary, + /// + /// 属性/字段不会被存储 + /// + Never, + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/CallerInfo.cs b/CLEditor.Core/Diagnostics/CallerInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..3e983cc630503644fd3fd3f0a673dd9ddd7e61d5 --- /dev/null +++ b/CLEditor.Core/Diagnostics/CallerInfo.cs @@ -0,0 +1,44 @@ +using CLEditor.Core.Annotations; +using System.Runtime.CompilerServices; + +namespace CLEditor.Core.Diagnostics +{ + public sealed class CallerInfo + { + /// + /// 包含调用方的源文件的完整路径。 这是编译时的文件路径 + /// + public readonly string FilePath; + /// + /// 调用者的方法或属性名称 + /// + public readonly string MemberName; + /// + /// 调用方法的源文件中的行号 + /// + public readonly int LineNumber; + + private CallerInfo(string filePath, string memberName, int lineNumber) { + FilePath = filePath; + MemberName = memberName; + LineNumber = lineNumber; + } + + /// + /// 获取调用者信息 + /// + /// + /// + /// + /// + [NotNull] + public static CallerInfo Get([CallerFilePath] string sourceFilePath = "", [CallerMemberName] string memberName = "", [CallerLineNumber] int sourceLineNumber = 0) { + return new CallerInfo(sourceFilePath, memberName, sourceLineNumber); + } + + public override string ToString() + { + return $"{FilePath}:{MemberName}:{LineNumber}"; + } + } +} diff --git a/CLEditor.Core/Diagnostics/ExceptionInfo.cs b/CLEditor.Core/Diagnostics/ExceptionInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..c40c82ff7936c95b4cfcf67ab4b625bb62675f92 --- /dev/null +++ b/CLEditor.Core/Diagnostics/ExceptionInfo.cs @@ -0,0 +1,69 @@ +using System; +using System.Text; +using CLEditor.Core.Annotations; + +namespace CLEditor.Core.Diagnostics +{ + /// + /// 此类用于存储异常的某些属性。 它是可序列化的 + /// + [DataContract] + public sealed class ExceptionInfo + { + public ExceptionInfo() + { + } + + public ExceptionInfo([NotNull]Exception exception) + { + if (exception == null) + { + throw new ArgumentException(nameof(exception)); + } + + Message = exception.Message; + StackTrace = exception.StackTrace; + TypeFullName = exception.GetType().FullName; + TypeName = exception.GetType().Name; + InnerException = exception.InnerException != null ? new ExceptionInfo(exception.InnerException) : null; + } + + /// + /// 获取或设置异常的消息 + /// + public string Message { get; set; } + + /// + /// 获取或设置异常的堆栈跟踪 + /// + public string StackTrace { get; set; } + + /// + /// 获取或设置异常类型的全名 + /// + public string TypeFullName { get; set; } + + /// + /// 获取或设置异常类型的名称 + /// + public string TypeName { get; set; } + + public ExceptionInfo InnerException { get; set; } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.AppendLine(Message); + if (StackTrace != null) + { + sb.AppendLine(StackTrace); + } + + if (InnerException != null) + { + sb.AppendFormat("内部异常: {0}{1}", InnerException, Environment.NewLine); + } + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/ILogMessage.cs b/CLEditor.Core/Diagnostics/ILogMessage.cs new file mode 100644 index 0000000000000000000000000000000000000000..1d4f9304520c02f16a9804b91fdd8878f9a9e276 --- /dev/null +++ b/CLEditor.Core/Diagnostics/ILogMessage.cs @@ -0,0 +1,29 @@ +namespace CLEditor.Core.Diagnostics +{ + /// + /// 日志记录基础结构使用的日志消息的基本接口 + /// + public interface ILogMessage + { + /// + /// 该模块是系统逻辑部分的标识符。 + /// 它可以是类名,命名空间或未链接到代码层次结构的常规字符串。 + /// + string Module { get; set; } + + /// + /// 获取或设置此消息的类型 + /// + LogMessageType Type { get; set; } + + /// + /// 获取或设置文本 + /// + string Text { get; set; } + + /// + /// 获取或设置异常信息 + /// + ExceptionInfo ExceptionInfo { get; } + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/ILogger.cs b/CLEditor.Core/Diagnostics/ILogger.cs new file mode 100644 index 0000000000000000000000000000000000000000..b5c229ee5e27d79f9b9412989cfdfce759d4a4fb --- /dev/null +++ b/CLEditor.Core/Diagnostics/ILogger.cs @@ -0,0 +1,19 @@ +namespace CLEditor.Core.Diagnostics +{ + /// + /// 用于记录的接口 + /// + public interface ILogger + { + /// + /// 获取此记录器引用的模块 + /// + string Module { get; } + + /// + /// 记录指定的日志消息 + /// + /// 日志消息 + void Log(ILogMessage logMessage); + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/LogMessage.cs b/CLEditor.Core/Diagnostics/LogMessage.cs new file mode 100644 index 0000000000000000000000000000000000000000..9b6850d2b74c2caeabbd0581aff40390f65bc69d --- /dev/null +++ b/CLEditor.Core/Diagnostics/LogMessage.cs @@ -0,0 +1,44 @@ +using System; + +namespace CLEditor.Core.Diagnostics +{ + /// + /// 日志记录基础结构使用的基本日志消息 + /// + public class LogMessage : ILogMessage + { + /// + /// 获取或设置模块 + /// 该模块是系统逻辑部分的标识符。 它可以是类名,命名空间或未链接到代码层次结构的常规字符串 + /// + public string Module { get; set; } + /// + /// 获取或设置此消息的类型 + /// + public LogMessageType Type { get; set; } + public string Text { get; set; } + /// + /// 获取或设置异常 + /// + public Exception Exception { get; set; } + /// + /// 获取或设置调用者信息 + /// + public CallerInfo CallerInfo { get; set; } + + public ExceptionInfo ExceptionInfo => Exception != null ? new ExceptionInfo(Exception) : null; + + public LogMessage(string module, LogMessageType type, string text, Exception exception, CallerInfo callerInfo) { + Module = module; + Type = type; + Text = text; + Exception = exception; + CallerInfo = callerInfo; + } + + public override string ToString() + { + return $"{(Module != null ? $"[{Module}]: " : string.Empty)}{Type}: {Text}{(Exception != null ? $". {Exception}" : string.Empty)}"; + } + } +} diff --git a/CLEditor.Core/Diagnostics/LogMessageType.cs b/CLEditor.Core/Diagnostics/LogMessageType.cs new file mode 100644 index 0000000000000000000000000000000000000000..e64f3ef875a40fa5864e53ee4c40e7fcea4061b8 --- /dev/null +++ b/CLEditor.Core/Diagnostics/LogMessageType.cs @@ -0,0 +1,31 @@ +namespace CLEditor.Core.Diagnostics +{ + [DataContract] + public enum LogMessageType + { + /// + /// 调试消息(级别0) + /// + Debug = 0, + /// + /// 详细消息(级别1) + /// + Verbose = 1, + /// + /// 常规信息消息(级别2) + /// + Info = 2, + /// + /// 警告消息(级别3) + /// + Warning = 3, + /// + /// 错误消息(级别4) + /// + Error = 4, + /// + /// 致命错误消息(级别5) + /// + Fatal = 5, + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/Logger.cs b/CLEditor.Core/Diagnostics/Logger.cs new file mode 100644 index 0000000000000000000000000000000000000000..ec9a0754a92337dd1c13f52d4916d4a697a8be48 --- /dev/null +++ b/CLEditor.Core/Diagnostics/Logger.cs @@ -0,0 +1,53 @@ +using System; +using CLEditor.Core.Annotations; + +namespace CLEditor.Core.Diagnostics +{ + public abstract class Logger : ILogger + { + /// + /// 获取模块名称。 只读 + /// + public string Module { get; protected internal set; } + protected readonly bool[] EnableTypes; + /// + /// 获取或设置一个值,该值指示此实例是否存在错误。 + /// + public bool HasErrors { get; set; } + /// + /// 记录消息时发生 + /// + public event EventHandler MessageLogged; + + protected Logger() + { + EnableTypes = new bool[(int)LogMessageType.Fatal + 1]; + } + + public void Log([NotNull] ILogMessage logMessage) + { + if (logMessage == null) + { + throw new ArgumentNullException(nameof(logMessage)); + } + + if (logMessage.Type == LogMessageType.Error || logMessage.Type == LogMessageType.Fatal) + { + HasErrors = true; + } + + if (EnableTypes[(int)logMessage.Type]) + { + LogRaw(logMessage); + MessageLogged?.Invoke(this, new MessageLoggedEventArgs(logMessage)); + } + } + + /// + /// 用于记录消息的内部方法。 所有信息,调试,错误......等。 + /// 方法正在调用此方法 + /// + /// + protected abstract void LogRaw(ILogMessage logMessage); + } +} \ No newline at end of file diff --git a/CLEditor.Core/Diagnostics/LoggerExtensions.cs b/CLEditor.Core/Diagnostics/LoggerExtensions.cs new file mode 100644 index 0000000000000000000000000000000000000000..e9cdf01fe52965a49ff6ff10a1db97f4f5c7d78f --- /dev/null +++ b/CLEditor.Core/Diagnostics/LoggerExtensions.cs @@ -0,0 +1,19 @@ +using CLEditor.Core.Annotations; +using System; + +namespace CLEditor.Core.Diagnostics +{ + public static class LoggerExtensions + { + /// + /// 使用异常记录指定的详细消息 + /// + /// + /// + /// + /// + public static void Verbose([NotNull] this ILogger logger, string message, Exception exception, CallerInfo callerInfo = null) { + logger.Log(new LogMessage(logger.Module, LogMessageType.Verbose, message, exception, callerInfo)); + } + } +} diff --git a/CLEditor.Core/Diagnostics/MessageLoggedEventArgs.cs b/CLEditor.Core/Diagnostics/MessageLoggedEventArgs.cs new file mode 100644 index 0000000000000000000000000000000000000000..587d9eb04047708a701f097873118f96c0779726 --- /dev/null +++ b/CLEditor.Core/Diagnostics/MessageLoggedEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace CLEditor.Core.Diagnostics +{ + public class MessageLoggedEventArgs : EventArgs + { + public MessageLoggedEventArgs(ILogMessage message) + { + Message = message; + } + + /// + /// 获取已记录的消息 + /// + public ILogMessage Message { get; private set; } + } +} \ No newline at end of file diff --git a/CLEditor.Core/IO/DictionaryStore.cs b/CLEditor.Core/IO/DictionaryStore.cs new file mode 100644 index 0000000000000000000000000000000000000000..0378032a2987381f1b32b1cec613d4bf24462a2a --- /dev/null +++ b/CLEditor.Core/IO/DictionaryStore.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace CLEditor.Core.IO +{ + /// + /// Key-> Value存储将逐步保存在HDD上 + /// 线程安全且过程安全 + /// + /// 密钥的类型 + /// 值的类型 + public class DictionaryStore : Store> + { + + } +} \ No newline at end of file diff --git a/CLEditor.Core/IO/Store.cs b/CLEditor.Core/IO/Store.cs new file mode 100644 index 0000000000000000000000000000000000000000..49d7384790e0a951392f1139fa19fde6812ed4a0 --- /dev/null +++ b/CLEditor.Core/IO/Store.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; + +namespace CLEditor.Core.IO +{ + /// + /// 将逐步保存在HDD上的商店。 + /// 线程安全且过程安全 + /// + /// 商店中元素的类型 + public abstract class Store : IDisposable where T : new() + { + protected Stream stream; + /// + /// 执行与释放,释放或重置非托管资源相关的应用程序定义的任务 + /// 等待待处理操作完成 + /// + public void Dispose() + { + if (stream != null) + { + lock (stream) + { + stream.Dispose(); + stream = null; + } + } + } + } +} \ No newline at end of file diff --git a/CLEditor.Core/Storage/IOdbBackend.cs b/CLEditor.Core/Storage/IOdbBackend.cs new file mode 100644 index 0000000000000000000000000000000000000000..121722db3d17e6ee0fc364e70fcb6551e71db2a3 --- /dev/null +++ b/CLEditor.Core/Storage/IOdbBackend.cs @@ -0,0 +1,12 @@ +using System; + +namespace CLEditor.Core.Storage +{ + /// + /// 自定义对象数据库后端(ODB)的基类 + /// + public interface IOdbBackend : IDisposable + { + + } +} \ No newline at end of file diff --git a/CLEditor.Core/Storage/ObjectDatabase.cs b/CLEditor.Core/Storage/ObjectDatabase.cs new file mode 100644 index 0000000000000000000000000000000000000000..233af478d6389b32f8f3469b7f1ce96c1b115dbf --- /dev/null +++ b/CLEditor.Core/Storage/ObjectDatabase.cs @@ -0,0 +1,30 @@ +using System; + +namespace CLEditor.Core.Storage +{ + /// + /// 提供对对象数据库的访问 + /// + public class ObjectDatabase : IDisposable + { + /// + /// 读取时,先尝试backendRead2,然后是backendRead1。 + /// 写入时,尝试backendWrite + /// + private readonly IOdbBackend backendRead1, backendRead2, backendWrite; + + public void Dispose() + { + backendRead1.Dispose(); + if (backendRead2 != null && !ReferenceEquals(backendRead2, backendRead1)) + { + backendRead2.Dispose(); + } + + if (backendWrite != null && !ReferenceEquals(backendRead2, backendWrite) && !ReferenceEquals(backendRead2, backendRead1)) + { + backendWrite.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/CLEditor.Core/Storage/ObjectId.cs b/CLEditor.Core/Storage/ObjectId.cs new file mode 100644 index 0000000000000000000000000000000000000000..6bb8fc15a375845e26e5977695c4c5524be02b64 --- /dev/null +++ b/CLEditor.Core/Storage/ObjectId.cs @@ -0,0 +1,52 @@ +using System; + +namespace CLEditor.Core.Storage +{ + /// + /// 用于唯一标识数据的哈希 + /// + public unsafe struct ObjectId : IEquatable, IComparable + { + /// + /// Murmurhash3散列大小为128位 + /// + public const int HashSize = 16; + private const int HashSizeInUInt = HashSize / sizeof(uint); + private uint hash1, hash2, hash3, hash4; + + public bool Equals(ObjectId other) + { + fixed (uint* xPtr = &hash1) + { + var x1 = xPtr; + var y1 = &other.hash1; + + for (var i = 0; i < HashSizeInUInt; ++i) + { + if (*x1++ != *y1++) + return false; + } + } + + return true; + } + + public int CompareTo(ObjectId other) + { + fixed (uint* xPtr = &hash1) + { + var x1 = xPtr; + var y1 = &other.hash1; + + for (var i = 0; i < HashSizeInUInt; ++i) + { + var compareResult = (*x1++).CompareTo(*y1++); + if (compareResult != 0) + return compareResult; + } + } + + return 0; + } + } +} \ No newline at end of file diff --git a/CLEditor.sln b/CLEditor.sln index b04948a6ba0ddb209660a8510dee77173940be73..be1ef8c08a6118717937708e3c4eae6148ee80c7 100644 --- a/CLEditor.sln +++ b/CLEditor.sln @@ -11,6 +11,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SceneEditor", "SceneEditor\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLPipleline", "CLPipleline\CLPipleline.csproj", "{09A94A34-9EA3-40B0-9A5F-C9B7B6E8A496}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLEditor.BuildEngine", "CLEditor.BuildEngine\CLEditor.BuildEngine.csproj", "{F49C4C69-3A15-4201-8AA2-29E115A17311}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildEngine", "BuildEngine", "{C2329FBC-8B03-4A1F-9873-3688D3A0F679}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CLEditor.BuildEngine.Common", "CLEditor.BuildEngine.Common\CLEditor.BuildEngine.Common.csproj", "{14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,10 +71,38 @@ Global {09A94A34-9EA3-40B0-9A5F-C9B7B6E8A496}.Release|x64.Build.0 = Release|Any CPU {09A94A34-9EA3-40B0-9A5F-C9B7B6E8A496}.Release|x86.ActiveCfg = Release|Any CPU {09A94A34-9EA3-40B0-9A5F-C9B7B6E8A496}.Release|x86.Build.0 = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|x64.ActiveCfg = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|x64.Build.0 = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|x86.ActiveCfg = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Debug|x86.Build.0 = Debug|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|Any CPU.Build.0 = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|x64.ActiveCfg = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|x64.Build.0 = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|x86.ActiveCfg = Release|Any CPU + {F49C4C69-3A15-4201-8AA2-29E115A17311}.Release|x86.Build.0 = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|x64.ActiveCfg = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|x64.Build.0 = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|x86.ActiveCfg = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Debug|x86.Build.0 = Debug|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|Any CPU.Build.0 = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|x64.ActiveCfg = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|x64.Build.0 = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|x86.ActiveCfg = Release|Any CPU + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F49C4C69-3A15-4201-8AA2-29E115A17311} = {C2329FBC-8B03-4A1F-9873-3688D3A0F679} + {14E96242-DA07-4408-BFD5-CEB6D2FE9CCE} = {C2329FBC-8B03-4A1F-9873-3688D3A0F679} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {09D24DF9-151B-4065-8E04-AA89C79159C9} EndGlobalSection diff --git a/CLEditor/CLEditor.csproj b/CLEditor/CLEditor.csproj index 006bc751ce51f45408f8ead469026fb23cb63534..c98a15f022ad64fb44f74e1402e534ca3b900c05 100644 --- a/CLEditor/CLEditor.csproj +++ b/CLEditor/CLEditor.csproj @@ -552,6 +552,7 @@ + PreserveNewest @@ -959,6 +960,9 @@ PreserveNewest + + + diff --git a/CLEditor/CreateScriptView.xaml b/CLEditor/CreateScriptView.xaml index fc8c8e72fa7784e51d62e7dd42501bef8dfaec90..f1a9725d8c955ad79fd9361156a80f5e1ede2eae 100644 --- a/CLEditor/CreateScriptView.xaml +++ b/CLEditor/CreateScriptView.xaml @@ -11,6 +11,7 @@ + @@ -18,7 +19,12 @@ MinWidth="200" x:Name="ScriptName" Margin="5 0 0 0"> -