升级
This commit is contained in:
		
							parent
							
								
									1e8889aecc
								
							
						
					
					
						commit
						411204b1ac
					
				@ -38,7 +38,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
        {
 | 
			
		||||
            if (element == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException($"{nameof(element)} is null");
 | 
			
		||||
                throw new ArgumentNullException(nameof(element));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (element.Name.Namespace != ModXml.EalaAsset)
 | 
			
		||||
@ -62,7 +62,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
        {
 | 
			
		||||
            if (asset is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException($"{nameof(asset)} is null");
 | 
			
		||||
                throw new ArgumentNullException(nameof(asset));
 | 
			
		||||
            }
 | 
			
		||||
            Type = asset.TypeName;
 | 
			
		||||
            Name = asset.InstanceName;
 | 
			
		||||
@ -74,13 +74,13 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Equals(AssetEntry entry)
 | 
			
		||||
        public bool Equals(AssetEntry? entry)
 | 
			
		||||
        {
 | 
			
		||||
            return this == entry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // override object.Equals
 | 
			
		||||
        public override bool Equals(object obj)
 | 
			
		||||
        public override bool Equals(object? obj)
 | 
			
		||||
        {
 | 
			
		||||
            //       
 | 
			
		||||
            // See the full list of guidelines at
 | 
			
		||||
@ -97,7 +97,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
            return this == entry;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator ==(AssetEntry a, AssetEntry b)
 | 
			
		||||
        public static bool operator ==(AssetEntry? a, AssetEntry? b)
 | 
			
		||||
        {
 | 
			
		||||
            if (a is null || b is null)
 | 
			
		||||
            {
 | 
			
		||||
@ -112,7 +112,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
            return a.Type == b.Type && a.InstanceId == b.InstanceId;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator !=(AssetEntry a, AssetEntry b)
 | 
			
		||||
        public static bool operator !=(AssetEntry? a, AssetEntry? b)
 | 
			
		||||
        {
 | 
			
		||||
            return !(a == b);
 | 
			
		||||
        }
 | 
			
		||||
@ -123,31 +123,31 @@ namespace HashCalculator.GUI
 | 
			
		||||
            return HashCode.Combine(Type, InstanceId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public int CompareTo(AssetEntry other)
 | 
			
		||||
        public int CompareTo(AssetEntry? other)
 | 
			
		||||
        {
 | 
			
		||||
            if (other is null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException($"{nameof(other)} is null");
 | 
			
		||||
                throw new ArgumentNullException(nameof(other));
 | 
			
		||||
            }
 | 
			
		||||
            return string.CompareOrdinal(NameString, other.NameString);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator <(AssetEntry left, AssetEntry right)
 | 
			
		||||
        public static bool operator <(AssetEntry? left, AssetEntry? right)
 | 
			
		||||
        {
 | 
			
		||||
            return left is null ? right is object : left.CompareTo(right) < 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator <=(AssetEntry left, AssetEntry right)
 | 
			
		||||
        public static bool operator <=(AssetEntry? left, AssetEntry? right)
 | 
			
		||||
        {
 | 
			
		||||
            return left is null || left.CompareTo(right) <= 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator >(AssetEntry left, AssetEntry right)
 | 
			
		||||
        public static bool operator >(AssetEntry? left, AssetEntry? right)
 | 
			
		||||
        {
 | 
			
		||||
            return left is object && left.CompareTo(right) > 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool operator >=(AssetEntry left, AssetEntry right)
 | 
			
		||||
        public static bool operator >=(AssetEntry? left, AssetEntry? right)
 | 
			
		||||
        {
 | 
			
		||||
            return left is null ? right is null : left.CompareTo(right) >= 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								Command.cs
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Command.cs
									
									
									
									
									
								
							@ -1,5 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
@ -12,8 +11,8 @@ namespace HashCalculator.GUI
 | 
			
		||||
        private readonly Action<Exception> _onAsyncException;
 | 
			
		||||
        private bool _canExecute = true;
 | 
			
		||||
 | 
			
		||||
        public bool CanExecuteValue 
 | 
			
		||||
        { 
 | 
			
		||||
        public bool CanExecuteValue
 | 
			
		||||
        {
 | 
			
		||||
            get => _canExecute;
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
@ -27,26 +26,25 @@ namespace HashCalculator.GUI
 | 
			
		||||
        public Command(Func<T, Task> action, Action<Exception>? onAsyncException = null)
 | 
			
		||||
        {
 | 
			
		||||
            _action = action;
 | 
			
		||||
            _onAsyncException = onAsyncException ?? (exception => 
 | 
			
		||||
            _onAsyncException = onAsyncException ?? (exception =>
 | 
			
		||||
            {
 | 
			
		||||
                MessageBox.Show($"Unhandled async exception in {nameof(Command<T>)}: {exception}");
 | 
			
		||||
                Application.Current.Shutdown(1);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool CanExecute(object parameter)
 | 
			
		||||
        public bool CanExecute(object? parameter)
 | 
			
		||||
        {
 | 
			
		||||
            return _canExecute;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Globalization", "CA1303:请不要将文本作为本地化参数传递", Justification = "<挂起>")]
 | 
			
		||||
        public void Execute(object parameter)
 | 
			
		||||
        public void Execute(object? parameter)
 | 
			
		||||
        {
 | 
			
		||||
            if (!_canExecute)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if(!(parameter is T typed))
 | 
			
		||||
            if (!(parameter is T typed))
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException($"{nameof(parameter)} wrong type");
 | 
			
		||||
            }
 | 
			
		||||
@ -56,7 +54,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
        public Task ExecuteTask(T parameter) => _action(parameter);
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        private async void ExecuteTaskInternal(Task task)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
@ -115,7 +112,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
        public Task ExecuteTask() => _action();
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        private async void ExecuteTaskInternal(Task task)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
            TracerListener.StartListening(s => action(() => ViewModel.TraceText += s));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        public async Task OnMainInputDecided(InputEntry selected)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
@ -78,7 +77,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        private static Task<string> CalculateBinaryHash(string filePath, CancellationToken cancel)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.Run(() =>
 | 
			
		||||
@ -201,7 +199,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Reliability", "CA2000:丢失范围之前释放对象", Justification = "<挂起>")]
 | 
			
		||||
        private async Task LoadXml(string path)
 | 
			
		||||
        {
 | 
			
		||||
            await CancelLoadingXml().ConfigureAwait(true);
 | 
			
		||||
@ -234,7 +231,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }, "SAGE FastHash 计算器 - XML 加载失败…", "XML 文件加载失败,也许,你选择的 XML 文件并不是红警3使用的那种……\r\n").ConfigureAwait(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        private async Task LoadXmlInternal(string path, CancellationToken token)
 | 
			
		||||
        {
 | 
			
		||||
            var modXml = new ModXml(path, token);
 | 
			
		||||
@ -343,14 +339,15 @@ namespace HashCalculator.GUI
 | 
			
		||||
                    throw new NotSupportedException();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                baseDirectory.GetFiles("*.csf");
 | 
			
		||||
                var parent = baseDirectory.Parent;
 | 
			
		||||
                var searchDirectories =
 | 
			
		||||
                    parent.GetDirectories($"{baseDirectory.Name[0]}*")
 | 
			
		||||
                    .Prepend(parent.Parent)
 | 
			
		||||
                    .Prepend(baseDirectory);
 | 
			
		||||
                searchDirectories = searchDirectories
 | 
			
		||||
                    .Concat(searchDirectories.SelectMany(x => x.GetDirectories("Additional")));
 | 
			
		||||
                var searchFrom = new List<DirectoryInfo> { baseDirectory };
 | 
			
		||||
                if (baseDirectory.Parent is { } parent)
 | 
			
		||||
                {
 | 
			
		||||
                    searchFrom.AddRange(parent.GetDirectories($"{baseDirectory.Name[0]}*"));
 | 
			
		||||
                    searchFrom.Add(parent);
 | 
			
		||||
                }
 | 
			
		||||
                var searchDirectories = new[] { "Additional", "Misc" }
 | 
			
		||||
                    .SelectMany(n => searchFrom.SelectMany(x => x.GetDirectories(n)))
 | 
			
		||||
                    .Concat(searchFrom);
 | 
			
		||||
                var csfs = from directories in searchDirectories
 | 
			
		||||
                           from data in directories.GetDirectories("Data")
 | 
			
		||||
                           from csf in data.GetFiles("*.csf")
 | 
			
		||||
@ -415,7 +412,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
            return VirtualFileSystem.GetFileName(path).StartsWith(what, StringComparison.OrdinalIgnoreCase);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        private static async Task ExceptionWrapepr(Func<Task> action, string errorTitle, string preErrorMessage)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
 | 
			
		||||
@ -105,7 +105,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
            CloseCommand = new Command<CopyableBox>(async window =>
 | 
			
		||||
            {
 | 
			
		||||
                CloseCommand.CanExecuteValue = false;
 | 
			
		||||
                CloseCommand!.CanExecuteValue = false;
 | 
			
		||||
                Notify(nameof(CloseButtonText));
 | 
			
		||||
 | 
			
		||||
                if (_task != null)
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
        {
 | 
			
		||||
            Timer = new DispatcherTimer(interval, DispatcherPriority.Normal, (s, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (Timer.IsEnabled && (TimeSinceCreation > wait))
 | 
			
		||||
                if (Timer!.IsEnabled && (TimeSinceCreation > wait))
 | 
			
		||||
                {
 | 
			
		||||
                    action(this);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
 | 
			
		||||
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk">
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <UseWPF>true</UseWPF>
 | 
			
		||||
    <OutputType>WinExe</OutputType>
 | 
			
		||||
    <TargetFramework>net472</TargetFramework>
 | 
			
		||||
    <RootNamespace>HashCalculator.GUI</RootNamespace>
 | 
			
		||||
    <TargetFramework>net5.0-windows</TargetFramework>
 | 
			
		||||
    <LangVersion>8.0</LangVersion>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
    <UseWPF>true</UseWPF>
 | 
			
		||||
@ -11,30 +10,14 @@
 | 
			
		||||
    <UserSecretsId>bf77c300-44f6-46ea-be94-f50d6993b55b</UserSecretsId>
 | 
			
		||||
    <StartupObject>HashCalculator.GUI.Program</StartupObject>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="1.1.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
 | 
			
		||||
      <PrivateAssets>all</PrivateAssets>
 | 
			
		||||
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
 | 
			
		||||
    </PackageReference>
 | 
			
		||||
    <PackageReference Include="Mvp.Xml" Version="2.3.0" />
 | 
			
		||||
    <PackageReference Include="System.Threading.Tasks.Dataflow" Version="4.11.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.11.0" />
 | 
			
		||||
    <PackageReference Include="Mvp.Xml.NetStandard" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="System.Threading.Tasks.Dataflow" Version="5.0.0" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Reference Include="System.Windows.Presentation" />
 | 
			
		||||
    <Reference Include="TechnologyAssembler.Core">
 | 
			
		||||
      <HintPath>TechnologyAssembler.Core.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
  <Target Name="CustomAfterResolveReferences" AfterTargets="AfterResolveReferences">
 | 
			
		||||
    <ItemGroup>
 | 
			
		||||
      <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
 | 
			
		||||
        <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
 | 
			
		||||
      </EmbeddedResource>
 | 
			
		||||
    </ItemGroup>
 | 
			
		||||
  </Target>
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										31
									
								
								HashCalculator.GUI.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								HashCalculator.GUI.sln
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
 | 
			
		||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
			
		||||
# Visual Studio Version 16
 | 
			
		||||
VisualStudioVersion = 16.0.30907.101
 | 
			
		||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HashCalculator.GUI", "HashCalculator.GUI.csproj", "{C214AFC4-5969-42D6-9524-7C5AF0719188}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
			
		||||
		Debug|Any CPU = Debug|Any CPU
 | 
			
		||||
		Debug|x86 = Debug|x86
 | 
			
		||||
		Release|Any CPU = Release|Any CPU
 | 
			
		||||
		Release|x86 = Release|x86
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Debug|x86.ActiveCfg = Debug|x86
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Debug|x86.Build.0 = Debug|x86
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Release|x86.ActiveCfg = Release|x86
 | 
			
		||||
		{C214AFC4-5969-42D6-9524-7C5AF0719188}.Release|x86.Build.0 = Release|x86
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(SolutionProperties) = preSolution
 | 
			
		||||
		HideSolutionNode = FALSE
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
			
		||||
		SolutionGuid = {DCF48A50-EE93-433D-A957-650FEB2779E9}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
EndGlobal
 | 
			
		||||
							
								
								
									
										42
									
								
								ModXml.cs
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								ModXml.cs
									
									
									
									
									
								
							@ -44,12 +44,14 @@ namespace HashCalculator.GUI
 | 
			
		||||
        public ModXml(string xmlPath, CancellationToken token)
 | 
			
		||||
        {
 | 
			
		||||
            BaseDirectory = new DirectoryInfo(FindBaseDirectory(xmlPath));
 | 
			
		||||
            var allMods = BaseDirectory.Parent;
 | 
			
		||||
            var allMods = BaseDirectory.Parent 
 | 
			
		||||
                ?? throw new ArgumentException($"{nameof(xmlPath)}'s {nameof(BaseDirectory)} doesn't have a parent");
 | 
			
		||||
            if (!allMods.Name.Equals("Mods", StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
            {
 | 
			
		||||
                throw new DirectoryNotFoundException();
 | 
			
		||||
            }
 | 
			
		||||
            var allModsParent = allMods.Parent;
 | 
			
		||||
            var allModsParent = allMods.Parent
 | 
			
		||||
                ?? throw new ArgumentException($"SDK Mods folder doesn't have a parent");
 | 
			
		||||
            using var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
 | 
			
		||||
            if (!(hklm.GetValue(RegistryPath) is string sdkRootPath))
 | 
			
		||||
            {
 | 
			
		||||
@ -129,7 +131,9 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var document = GetFile(fullPath);
 | 
			
		||||
            if (document.Root.Name != EalaAsset + "AssetDeclaration" && document.Root.Name != "AssetDeclaration")
 | 
			
		||||
            var rootName = document.Root?.Name 
 | 
			
		||||
                ?? throw new InvalidDataException("Document doesn't have a root");
 | 
			
		||||
            if (rootName != EalaAsset + "AssetDeclaration" && rootName != "AssetDeclaration")
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotSupportedException();
 | 
			
		||||
            }
 | 
			
		||||
@ -204,11 +208,13 @@ namespace HashCalculator.GUI
 | 
			
		||||
        private static string FindBaseDirectory(string currentPath)
 | 
			
		||||
        {
 | 
			
		||||
            var file = new FileInfo(currentPath);
 | 
			
		||||
            if (File.Exists(Path.Combine(file.DirectoryName, "Data", "mod.xml")))
 | 
			
		||||
            var directoryName = file.DirectoryName
 | 
			
		||||
                ?? throw new ArgumentException($"{nameof(currentPath)} doens't have a directory");
 | 
			
		||||
            if (File.Exists(Path.Combine(directoryName, "Data", "mod.xml")))
 | 
			
		||||
            {
 | 
			
		||||
                return file.DirectoryName;
 | 
			
		||||
                return directoryName;
 | 
			
		||||
            }
 | 
			
		||||
            return FindBaseDirectory(file.DirectoryName);
 | 
			
		||||
            return FindBaseDirectory(directoryName);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -221,11 +227,11 @@ namespace HashCalculator.GUI
 | 
			
		||||
            Paths = paths;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
 | 
			
		||||
        public override object GetEntity(Uri? absoluteUri, string? role, Type? ofObjectToReturn)
 | 
			
		||||
        {
 | 
			
		||||
            if (absoluteUri == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException($"{nameof(absoluteUri)} is null");
 | 
			
		||||
                throw new ArgumentNullException(nameof(absoluteUri));
 | 
			
		||||
            }
 | 
			
		||||
            if (ofObjectToReturn != null && ofObjectToReturn != typeof(Stream))
 | 
			
		||||
            {
 | 
			
		||||
@ -234,8 +240,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
            return File.OpenRead(absoluteUri.LocalPath);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Globalization", "CA1303:请不要将文本作为本地化参数传递", Justification = "<挂起>")]
 | 
			
		||||
        public override Uri ResolveUri(Uri baseUri, string relativeUri)
 | 
			
		||||
        public override Uri ResolveUri(Uri? baseUri, string? relativeUri)
 | 
			
		||||
        {
 | 
			
		||||
            if (baseUri == null)
 | 
			
		||||
            {
 | 
			
		||||
@ -247,22 +252,13 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
            if (relativeUri == null)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentNullException($"{nameof(relativeUri)} is null");
 | 
			
		||||
                throw new ArgumentNullException(nameof(relativeUri));
 | 
			
		||||
            }
 | 
			
		||||
            return new Uri(Path.GetFullPath(ResolvePath(relativeUri, Path.GetDirectoryName(baseUri.LocalPath))));
 | 
			
		||||
            var localPath = Path.GetDirectoryName(baseUri.LocalPath) 
 | 
			
		||||
                ?? throw new ArgumentException($"{nameof(baseUri)} doesn't have a local path");
 | 
			
		||||
            return new Uri(Path.GetFullPath(ResolvePath(relativeUri, localPath)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Task<object> GetEntityAsync(Uri absoluteUri, string role, Type ofObjectToReturn)
 | 
			
		||||
        {
 | 
			
		||||
            return base.GetEntityAsync(absoluteUri, role, ofObjectToReturn);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool SupportsType(Uri absoluteUri, Type type)
 | 
			
		||||
        {
 | 
			
		||||
            return base.SupportsType(absoluteUri, type);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Globalization", "CA1303:请不要将文本作为本地化参数传递", Justification = "<挂起>")]
 | 
			
		||||
        private string ResolvePath(string href, string currentDirectory)
 | 
			
		||||
        {
 | 
			
		||||
            var splitted = href.Split(new[] { ':' }, 2);
 | 
			
		||||
 | 
			
		||||
@ -19,16 +19,17 @@ namespace HashCalculator.GUI
 | 
			
		||||
            }
 | 
			
		||||
            catch(Exception exception)
 | 
			
		||||
            {
 | 
			
		||||
                ErrorBox($"发生了无法处理的错误:\r\n{exception.ToString()}\r\n可以尝试在百度红警3吧联系岚依");
 | 
			
		||||
                ErrorBox($"发生了无法处理的错误:\r\n{exception}\r\n可以尝试在百度红警3吧联系岚依");
 | 
			
		||||
                throw;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
 | 
			
		||||
        private static Assembly OnResolveAssembly(object? sender, ResolveEventArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            var executingAssembly = Assembly.GetExecutingAssembly();
 | 
			
		||||
            var assemblyName = new AssemblyName(args.Name);
 | 
			
		||||
            var nameString = assemblyName.Name;
 | 
			
		||||
            var nameString = assemblyName.Name 
 | 
			
		||||
                ?? throw new InvalidOperationException("Assembly does not have an name");
 | 
			
		||||
 | 
			
		||||
            var paths = new[] { $"{nameString}.dll" }.AsEnumerable();
 | 
			
		||||
            const string resourceExtenstion = ".resources";
 | 
			
		||||
@ -36,7 +37,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
            {
 | 
			
		||||
                paths = paths.Append(nameString.Insert(nameString.Length - resourceExtenstion.Length, ".g"));
 | 
			
		||||
            }
 | 
			
		||||
            if (!assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture))
 | 
			
		||||
            if (!Equals(assemblyName.CultureInfo, CultureInfo.InvariantCulture))
 | 
			
		||||
            {
 | 
			
		||||
                paths = paths.Select(x => $"{assemblyName.CultureInfo}\\{x}").Concat(paths);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										65
									
								
								ScriptCompiler.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								ScriptCompiler.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
using Microsoft.CodeAnalysis;
 | 
			
		||||
using Microsoft.CodeAnalysis.CSharp;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using TechnologyAssembler;
 | 
			
		||||
 | 
			
		||||
namespace HashCalculator.GUI
 | 
			
		||||
{
 | 
			
		||||
    internal class ScriptCompiler
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly MetadataReference[] _references = new[]
 | 
			
		||||
        {
 | 
			
		||||
            typeof(object), // core
 | 
			
		||||
            typeof(Trace), // make sure trace is availaible
 | 
			
		||||
            typeof(Enumerable), // linq
 | 
			
		||||
            typeof(ScriptCompiler), // this
 | 
			
		||||
            typeof(TechnologyAssemblerCoreModule) // wed
 | 
			
		||||
        }.Select(t => MetadataReference.CreateFromFile(t.Assembly.Location)).ToArray();
 | 
			
		||||
 | 
			
		||||
        public static IEnumerable<(string Id, string Message)> CheckSyntax(string code)
 | 
			
		||||
        {
 | 
			
		||||
            var syntaxTree = CSharpSyntaxTree.ParseText(code);
 | 
			
		||||
            return syntaxTree.GetDiagnostics().Select(diagnostic => (diagnostic.Id, diagnostic.GetMessage()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool Compile(string code, object[] arguments, out IEnumerable<(string Id, string Message)> messages)
 | 
			
		||||
        {
 | 
			
		||||
            // define source code, then parse it (to the type used for compilation)
 | 
			
		||||
            var syntaxTree = CSharpSyntaxTree.ParseText(code);
 | 
			
		||||
 | 
			
		||||
            // define other necessary objects for compilation
 | 
			
		||||
            var assemblyName = $"Gen{Guid.NewGuid()}.dll";
 | 
			
		||||
 | 
			
		||||
            // analyse and generate IL code from syntax tree
 | 
			
		||||
            var compilation =
 | 
			
		||||
                CSharpCompilation.Create(assemblyName,
 | 
			
		||||
                                         syntaxTrees: new[] { syntaxTree },
 | 
			
		||||
                                         references: _references,
 | 
			
		||||
                                         options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
 | 
			
		||||
 | 
			
		||||
            using var ms = new MemoryStream();
 | 
			
		||||
            // write IL code into memory
 | 
			
		||||
            var result = compilation.Emit(ms);
 | 
			
		||||
            messages = result.Diagnostics.Select(diagnostic => (diagnostic.Id, diagnostic.GetMessage()));
 | 
			
		||||
 | 
			
		||||
            if (!result.Success)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // load this 'virtual' DLL so that we can use
 | 
			
		||||
            ms.Seek(0, SeekOrigin.Begin);
 | 
			
		||||
            var domain = AppDomain.CreateDomain($"runtime code {assemblyName}");
 | 
			
		||||
            var assembly = domain.Load(ms.ToArray());
 | 
			
		||||
            // create instance of the desired class and call the desired function
 | 
			
		||||
            var entryPoint = assembly.EntryPoint
 | 
			
		||||
                ?? throw new InvalidOperationException("Compiled assembly does not have an entry point");
 | 
			
		||||
            entryPoint.Invoke(null, arguments);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,5 +1,4 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using TechnologyAssembler.Core.Language;
 | 
			
		||||
@ -14,11 +13,11 @@ namespace HashCalculator.GUI
 | 
			
		||||
            get => Interlocked.CompareExchange(ref _provider, null, null);
 | 
			
		||||
            set
 | 
			
		||||
            {
 | 
			
		||||
                var provider = value is null 
 | 
			
		||||
                    ? null 
 | 
			
		||||
                var provider = value is null
 | 
			
		||||
                    ? null
 | 
			
		||||
                    : new CachedCsfTranslationProvider(value);
 | 
			
		||||
                Interlocked.Exchange(ref _provider, provider);
 | 
			
		||||
                ProviderChanged?.Invoke(null, null);
 | 
			
		||||
                ProviderChanged?.Invoke(null, EventArgs.Empty);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -28,7 +27,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
        public static string Translate(string what)
 | 
			
		||||
        {
 | 
			
		||||
            var provider = Provider;
 | 
			
		||||
            if(provider is null)
 | 
			
		||||
            if (provider is null)
 | 
			
		||||
            {
 | 
			
		||||
                return $"NoProvider:{what}";
 | 
			
		||||
            }
 | 
			
		||||
@ -50,7 +49,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
        public string GetString(string str)
 | 
			
		||||
        {
 | 
			
		||||
            if(!_cache.TryGetValue(str, out var value))
 | 
			
		||||
            if (!_cache.TryGetValue(str, out var value))
 | 
			
		||||
            {
 | 
			
		||||
                value = _provider.GetString(str);
 | 
			
		||||
                _cache.TryAdd(str, value);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										44
									
								
								ViewModel.cs
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								ViewModel.cs
									
									
									
									
									
								
							@ -1,14 +1,13 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Microsoft.Win32;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Collections.Specialized;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Diagnostics.CodeAnalysis;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.Win32;
 | 
			
		||||
using TechnologyAssembler.Core.IO;
 | 
			
		||||
 | 
			
		||||
namespace HashCalculator.GUI
 | 
			
		||||
@ -61,14 +60,14 @@ namespace HashCalculator.GUI
 | 
			
		||||
                FilterDisplayEntries.Execute(null);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        private bool _gameObjectOnly;
 | 
			
		||||
        public bool GameObjectOnly
 | 
			
		||||
        {
 | 
			
		||||
            get => _gameObjectOnly;
 | 
			
		||||
            set => SetField(ref _gameObjectOnly, value);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        public Command FilterDisplayEntries { get; }
 | 
			
		||||
 | 
			
		||||
        private int _totalCount;
 | 
			
		||||
@ -133,19 +132,19 @@ namespace HashCalculator.GUI
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    CancelXml.CanExecuteValue = false;
 | 
			
		||||
                    CancelXml!.CanExecuteValue = false;
 | 
			
		||||
                    await controller.CancelLoadingXml().ConfigureAwait(true);
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    CancelXml.CanExecuteValue = true;
 | 
			
		||||
                    CancelXml!.CanExecuteValue = true;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            LoadCsf = new Command<MainWindow>(async window =>
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    LoadCsf.CanExecuteValue = false;
 | 
			
		||||
                    LoadCsf!.CanExecuteValue = false;
 | 
			
		||||
                    var dialog = new OpenFileDialog
 | 
			
		||||
                    {
 | 
			
		||||
                        Multiselect = false,
 | 
			
		||||
@ -159,7 +158,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    LoadCsf.CanExecuteValue = true;
 | 
			
		||||
                    LoadCsf!.CanExecuteValue = true;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            FilterDisplayEntries = new Command(() =>
 | 
			
		||||
@ -221,9 +220,9 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
        private bool FilterDisplayEntry(AssetEntry entry)
 | 
			
		||||
        {
 | 
			
		||||
            if(GameObjectOnly)
 | 
			
		||||
            if (GameObjectOnly)
 | 
			
		||||
            {
 | 
			
		||||
                if(entry.Type != "GameObject")
 | 
			
		||||
                if (entry.Type != "GameObject")
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
@ -298,7 +297,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
            {
 | 
			
		||||
                if (value == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    if (Items.Count() <= 1)
 | 
			
		||||
                    if (Items?.Count() <= 1)
 | 
			
		||||
                    {
 | 
			
		||||
                        value = -1;
 | 
			
		||||
                    }
 | 
			
		||||
@ -353,13 +352,13 @@ namespace HashCalculator.GUI
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    BrowseCommand.CanExecuteValue = false;
 | 
			
		||||
                    SelectCommand.CanExecuteValue = false;
 | 
			
		||||
                    SelectCommand!.CanExecuteValue = false;
 | 
			
		||||
                    await controller.OnMainInputDecided(SelectedItem).ConfigureAwait(true);
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    BrowseCommand.CanExecuteValue = true;
 | 
			
		||||
                    SelectCommand.CanExecuteValue = true;
 | 
			
		||||
                    SelectCommand!.CanExecuteValue = true;
 | 
			
		||||
                    SelectedIndex = -1;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
@ -417,7 +416,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
                base.Text = value;
 | 
			
		||||
                if (value != SelectedItem?.ToString())
 | 
			
		||||
                {
 | 
			
		||||
                    if(AllManifests != null)
 | 
			
		||||
                    if (AllManifests != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        UpdateList(value);
 | 
			
		||||
                    }
 | 
			
		||||
@ -448,7 +447,6 @@ namespace HashCalculator.GUI
 | 
			
		||||
 | 
			
		||||
        public Command<ViewModel> SelectCommand { get; }
 | 
			
		||||
 | 
			
		||||
        [SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")]
 | 
			
		||||
        public BigInputViewModel(Controller controller)
 | 
			
		||||
        {
 | 
			
		||||
            SelectCommand = new Command<ViewModel>(async viewModel =>
 | 
			
		||||
@ -456,7 +454,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
                var mainInput = viewModel.MainInput;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    SelectCommand.CanExecuteValue = false;
 | 
			
		||||
                    SelectCommand!.CanExecuteValue = false;
 | 
			
		||||
                    mainInput.BrowseCommand.CanExecuteValue = false;
 | 
			
		||||
                    mainInput.SelectCommand.CanExecuteValue = false;
 | 
			
		||||
                    LastProcessedManifest = SelectedItem;
 | 
			
		||||
@ -464,14 +462,14 @@ namespace HashCalculator.GUI
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception exception)
 | 
			
		||||
                {
 | 
			
		||||
                    CopyableBox.ShowDialog("SAGE FastHash 计算器的错误" , _ =>
 | 
			
		||||
                    {
 | 
			
		||||
                        return Task.FromResult($"在加载 manifest 时发生错误:{exception}");
 | 
			
		||||
                    });
 | 
			
		||||
                    CopyableBox.ShowDialog("SAGE FastHash 计算器的错误", _ =>
 | 
			
		||||
                   {
 | 
			
		||||
                       return Task.FromResult($"在加载 manifest 时发生错误:{exception}");
 | 
			
		||||
                   });
 | 
			
		||||
                }
 | 
			
		||||
                finally
 | 
			
		||||
                {
 | 
			
		||||
                    SelectCommand.CanExecuteValue = true;
 | 
			
		||||
                    SelectCommand!.CanExecuteValue = true;
 | 
			
		||||
                    mainInput.BrowseCommand.CanExecuteValue = true;
 | 
			
		||||
                    mainInput.SelectCommand.CanExecuteValue = true;
 | 
			
		||||
                }
 | 
			
		||||
@ -526,7 +524,7 @@ namespace HashCalculator.GUI
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                foreach(var i in Enumerable.Range(0, base.Count).Reverse())
 | 
			
		||||
                foreach (var i in Enumerable.Range(0, base.Count).Reverse())
 | 
			
		||||
                {
 | 
			
		||||
                    var item = base[i];
 | 
			
		||||
                    if (ifRemove(item))
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user