diff --git a/src/Attributes/CommandLineArgumentAttribute.cs b/src/Attributes/CommandLineArgumentAttribute.cs
new file mode 100644
index 0000000..4cbfa04
--- /dev/null
+++ b/src/Attributes/CommandLineArgumentAttribute.cs
@@ -0,0 +1,26 @@
+namespace iFileProxy.Attributes
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ public class CommandLineArgumentAttribute : Attribute
+ {
+ ///
+ /// 长参数名 如: --dev-logger
+ ///
+ public string FullArgumentName { get; set; } = string.Empty;
+
+ ///
+ /// 短参数名 如: -d
+ ///
+ public string ShortArgumentName { get; set; } = new string(' ',4);
+
+ ///
+ /// 参数帮助文本
+ ///
+ public string Description { get; set; } = string.Empty;
+
+ ///
+ /// 是否需要参数值
+ ///
+ public bool NeedValue { get; set; } = false;
+ }
+}
diff --git a/src/Handlers/CmdArgsHandler.cs b/src/Handlers/CmdArgsHandler.cs
deleted file mode 100644
index d38270b..0000000
--- a/src/Handlers/CmdArgsHandler.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using iFileProxy.Config;
-using iFileProxy.Helpers;
-using iFileProxy.Services;
-namespace iFileProxy.Handlers
-{
- public class CmdArgsHandler
- {
- public static void ParseArgs(string[] args, IServiceProvider serviceProvider)
- {
- if (args.Length == 0)
- return;
- Dictionary helpStrings = [];
- helpStrings.Add("--init-db", "初始化数据库");
- helpStrings.Add("--dev-logger", "启用开发者logger");
- helpStrings.Add("--disable-startup-check", "禁用启动时程序配置自检");
- helpStrings.Add("--url=", "设置程序app.run() Url 如: http://0.0.0.0:1145");
-
- if (args.Contains("-h") || args.Contains("--help"))
- {
- Console.WriteLine("命令行参数帮助: ");
- foreach (var hs in helpStrings)
- {
- Console.WriteLine($"\t{hs.Key}\t{hs.Value}");
- }
- Environment.Exit(0);
- }
-
- CommandLineArgsHelper cmdlineHelper = new(args);
-
- if (cmdlineHelper.GetBooleanValue("--init-db"))
- {
- serviceProvider.GetRequiredService().TryInitialDB();
- }
- }
- }
-}
diff --git a/src/Handlers/CommandLine/CustomBindUrl.cs b/src/Handlers/CommandLine/CustomBindUrl.cs
new file mode 100644
index 0000000..15f6850
--- /dev/null
+++ b/src/Handlers/CommandLine/CustomBindUrl.cs
@@ -0,0 +1,15 @@
+using iFileProxy.Attributes;
+using iFileProxy.Interfaces;
+
+namespace iFileProxy.Handlers.CommandLine
+{
+ [CommandLineArgument(FullArgumentName = "--bind-url", ShortArgumentName = "-B", Description = "自定义绑定URL", NeedValue = true)]
+ public class CustomBindUrl(string[] args) : ICommandLineHandler
+ {
+ public void Process()
+ {
+ Console.WriteLine("当前正使用自定义URL绑定");
+ // 具体的实现在Program.cs中 此处仅作提示
+ }
+ }
+}
diff --git a/src/Handlers/CommandLine/DisablePreStartupCheck.cs b/src/Handlers/CommandLine/DisablePreStartupCheck.cs
new file mode 100644
index 0000000..f8ab29b
--- /dev/null
+++ b/src/Handlers/CommandLine/DisablePreStartupCheck.cs
@@ -0,0 +1,15 @@
+using iFileProxy.Attributes;
+using iFileProxy.Interfaces;
+
+namespace iFileProxy.Handlers.CommandLine
+{
+ [CommandLineArgument(FullArgumentName = "--disable-startup-check", ShortArgumentName = "-D", Description = "禁用配置文件启动前校验")]
+ public class DisablePreStartupCheck(string[] args) : ICommandLineHandler
+ {
+ public void Process()
+ {
+ Console.WriteLine("已禁用启动前配置文件校验");
+ // 具体的实现在Program.cs中 此处仅作提示
+ }
+ }
+}
diff --git a/src/Handlers/CommandLine/EnableDevLogger.cs b/src/Handlers/CommandLine/EnableDevLogger.cs
new file mode 100644
index 0000000..3208f60
--- /dev/null
+++ b/src/Handlers/CommandLine/EnableDevLogger.cs
@@ -0,0 +1,15 @@
+using iFileProxy.Attributes;
+using iFileProxy.Interfaces;
+
+namespace iFileProxy.Handlers.CommandLine
+{
+ [CommandLineArgument(FullArgumentName = "--dev-logging", ShortArgumentName = "-d", Description = "启用dev级别日志记录")]
+ public class EnableDevLogger(string[] args) : ICommandLineHandler
+ {
+ public void Process()
+ {
+ Console.WriteLine("developer logging is enabled.");
+ // 具体的实现在SerilogConfig.cs中 此处仅作提示
+ }
+ }
+}
diff --git a/src/Handlers/CommandLine/HelpHandler.cs b/src/Handlers/CommandLine/HelpHandler.cs
new file mode 100644
index 0000000..fcb78e1
--- /dev/null
+++ b/src/Handlers/CommandLine/HelpHandler.cs
@@ -0,0 +1,39 @@
+using iFileProxy.Attributes;
+using iFileProxy.Helpers;
+using iFileProxy.Interfaces;
+using iFileProxy.Services;
+using System.Reflection;
+
+namespace iFileProxy.Handlers.CommandLine
+{
+ [CommandLineArgument(FullArgumentName ="--help",ShortArgumentName = "-h", Description = "显示帮助文本")]
+ public class HelpHandler : ICommandLineHandler
+ {
+ string[] _args = [];
+ public HelpHandler(string[] args) {
+ _args = args;
+ }
+
+ public void Process()
+ {
+ Dictionary helpText = CommandLineArgumentDispatcher.GetHelpTextDict();
+ // 找到最长的键长度
+ int maxKeyLength = helpText.Keys.Max(key => key.Length);
+
+ // 打印表头
+ Console.WriteLine("参数(短参数, 长参数)\t解释");
+
+ // 打印每一行的帮助信息,确保对齐
+ foreach (var ht in helpText)
+ {
+ Console.WriteLine($" {ht.Key}{new string(' ', maxKeyLength - ht.Key.Length)}\t{ht.Value}");
+ }
+ Console.WriteLine(new string('\n',2));
+
+ Console.WriteLine($"程序编译日期(UTC+8): {MasterHelper.GetBuildTime(Assembly.GetExecutingAssembly())}");
+
+ Console.WriteLine();
+ Environment.Exit(0 );
+ }
+ }
+}
diff --git a/src/Handlers/CommandLine/InitDBHandler.cs b/src/Handlers/CommandLine/InitDBHandler.cs
new file mode 100644
index 0000000..7f9497c
--- /dev/null
+++ b/src/Handlers/CommandLine/InitDBHandler.cs
@@ -0,0 +1,21 @@
+using iFileProxy.Attributes;
+using iFileProxy.Interfaces;
+using iFileProxy.Services;
+
+namespace iFileProxy.Handlers.CommandLine
+{
+ [CommandLineArgument(FullArgumentName = "--init-db", ShortArgumentName = "-i", Description = "初始化数据库表结构")]
+ public class InitDBHandler : ICommandLineHandler
+ {
+ string[] _cmdArgs = [];
+ public InitDBHandler(string[] args) {
+ _cmdArgs = args;
+ }
+ public void Process()
+ {
+ DatabaseGateService gateService = new(new AppConfigService());
+ gateService.TryInitialDB();
+ Environment.Exit(0);
+ }
+ }
+}
diff --git a/src/Handlers/CommandLineArgumentDispatcher.cs b/src/Handlers/CommandLineArgumentDispatcher.cs
new file mode 100644
index 0000000..cbc0256
--- /dev/null
+++ b/src/Handlers/CommandLineArgumentDispatcher.cs
@@ -0,0 +1,90 @@
+using iFileProxy.Attributes;
+using iFileProxy.Config;
+using iFileProxy.Helpers;
+using iFileProxy.Interfaces;
+using Serilog;
+using System.Reflection;
+
+namespace iFileProxy.Handlers
+{
+ ///
+ /// 命令行参数调度器
+ ///
+ public class CommandLineArgumentDispatcher
+ {
+ private readonly static Serilog.ILogger _logger = Log.Logger.ForContext();
+
+ // 获取当前执行的程序集
+ static Assembly assembly = Assembly.GetExecutingAssembly();
+
+ // 获取程序集中所有的类型
+ static Type[] types = [];
+
+ public CommandLineArgumentDispatcher()
+ {
+ LoadAssemblyData();
+ }
+
+ static void LoadAssemblyData()
+ {
+ assembly = Assembly.GetExecutingAssembly();
+ types = assembly.GetTypes();
+ }
+
+
+ public static void Parse(string[] args)
+ {
+ LoadAssemblyData();
+ // 遍历所有类型,查找带有 CommandLineArgumentAttribute 的类
+ foreach (Type type in types)
+ {
+ // 检查类型是否具有 CommandLineArgumentAttribute
+ var attribute = type.GetCustomAttribute();
+ if (attribute != null && (args.Contains(attribute.FullArgumentName) || args.Contains(attribute.ShortArgumentName)))
+ {
+ var commandLineHandler = (ICommandLineHandler?)Activator.CreateInstance(type, [args]);
+ commandLineHandler?.Process();
+ }
+ }
+ }
+
+ public static Dictionary GetHelpTextDict()
+ {
+ static string GetHelpText(CommandLineArgumentAttribute attribute)
+ {
+ if (attribute.NeedValue && attribute.FullArgumentName.Trim() == string.Empty) // 需要值且没有长参数
+ {
+ return $"{attribute.ShortArgumentName}=";
+ }
+ else if (attribute.NeedValue && attribute.ShortArgumentName.Trim() == string.Empty)// 需要值且没有短参数
+ {
+ return $"{attribute.ShortArgumentName} {attribute.FullArgumentName}=";
+ }
+ else if (attribute.NeedValue && attribute.FullArgumentName.Trim() != "" && attribute.ShortArgumentName.Trim() != "") // 都需要
+ {
+ return $"{attribute.ShortArgumentName}=,{attribute.FullArgumentName}=";
+ }
+ else if (attribute.FullArgumentName.Trim() == "" && attribute.ShortArgumentName.Trim() == "") // 都没有
+ {
+ throw new ArgumentException("该参数长短参数名均为空 请联系软件开发者反馈");
+ }
+ else if (!attribute.NeedValue && attribute.FullArgumentName.Trim() == string.Empty)
+ return attribute.ShortArgumentName ;
+ else if (!attribute.NeedValue && attribute.ShortArgumentName.Trim() == string.Empty)
+ return $"{attribute.ShortArgumentName} {attribute.FullArgumentName}";
+ else
+ return $"{attribute.ShortArgumentName},{attribute.FullArgumentName}";
+ }
+ Dictionary r = [];
+ foreach (var handler in types)
+ {
+ var h = handler.GetCustomAttribute();
+ if (h != null)
+ {
+ r.Add(GetHelpText(h), h.Description);
+ }
+ }
+ return r;
+ }
+ }
+}
diff --git a/src/Helpers/CommandLineArgsHelper.cs b/src/Helpers/CommandLineArgsHelper.cs
index 30efed3..19a378e 100644
--- a/src/Helpers/CommandLineArgsHelper.cs
+++ b/src/Helpers/CommandLineArgsHelper.cs
@@ -23,13 +23,13 @@ namespace iFileProxy.Helpers
var parts = arg.Split(['='], 2);
if (parts.Length == 2)
{
- parameters[parts[0].TrimStart('-')] = parts[1];
+ parameters[parts[0]] = parts[1];
}
}
else
{
// 如果参数是没有值的标志性参数(比如 --dev-logger)
- parameters[arg.TrimStart('-')] = "true";
+ parameters[arg] = "true";
}
}
@@ -39,12 +39,34 @@ namespace iFileProxy.Helpers
// 获取指定参数的值,若无值则返回null
public string? GetStringValue(string key)
{
- return _parameters.ContainsKey(key) ? _parameters[key] : null;
+ // 如果 key 包含多个等效键(用 | 分隔),则拆分为数组
+ string[] keys = key.Contains("|")
+ ? key.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
+ : [key];
+
+ foreach (var k in keys)
+ {
+ if (_parameters.TryGetValue(k, out string? value))
+ {
+ return value;
+ }
+ }
+
+ // 如果没有任何键匹配,默认返回 null
+ return null;
}
// 获取指定参数的布尔值,若参数值是 "true" 则返回true,否则返回false
public bool GetBooleanValue(string key)
{
+ string[] args = [];
+ if (key.Contains("|"))
+ args = key.Split('|',StringSplitOptions.RemoveEmptyEntries|StringSplitOptions.TrimEntries);
+ foreach (var arg in args)
+ {
+ if (_parameters.ContainsKey(arg) && _parameters[arg].Equals("true", StringComparison.CurrentCultureIgnoreCase))
+ return true;
+ }
return _parameters.ContainsKey(key) && _parameters[key].Equals("true", StringComparison.CurrentCultureIgnoreCase);
}
}
diff --git a/src/Helpers/MasterHelper.cs b/src/Helpers/MasterHelper.cs
index 10dd71d..2536ffd 100644
--- a/src/Helpers/MasterHelper.cs
+++ b/src/Helpers/MasterHelper.cs
@@ -1,7 +1,9 @@
using iFileProxy.Config;
using iFileProxy.Models;
using Serilog;
+using System.Globalization;
using System.Net;
+using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -228,5 +230,25 @@ namespace iFileProxy.Helpers
return exp1.IsMatch(url) || exp2.IsMatch(url) || exp3.IsMatch(url) || exp4.IsMatch(url) || exp5.IsMatch(url);
}
+ // copy from https://summerlight.com/archives/184
+ public static DateTime GetBuildTime(Assembly assembly)
+ {
+ const string buildVersionMetadataPrefix = "+build";
+
+ var attribute = assembly.GetCustomAttribute();
+ if (attribute?.InformationalVersion != null)
+ {
+ var value = attribute.InformationalVersion;
+ var index = value.IndexOf(buildVersionMetadataPrefix, StringComparison.Ordinal);
+ if (index > 0)
+ {
+ value = value[(index + buildVersionMetadataPrefix.Length)..];
+ if (DateTime.TryParseExact(value, "yyyyMMddHHmmssZ", CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
+ return result;
+ }
+ }
+ return default;
+ }
+
}
}
diff --git a/src/Interfaces/ICommandLineHandler.cs b/src/Interfaces/ICommandLineHandler.cs
new file mode 100644
index 0000000..fe60139
--- /dev/null
+++ b/src/Interfaces/ICommandLineHandler.cs
@@ -0,0 +1,9 @@
+using iFileProxy.Services;
+
+namespace iFileProxy.Interfaces
+{
+ public interface ICommandLineHandler
+ {
+ public void Process();
+ }
+}
diff --git a/src/Program.cs b/src/Program.cs
index e49fe04..eb0061f 100644
--- a/src/Program.cs
+++ b/src/Program.cs
@@ -8,6 +8,7 @@ using Serilog;
using System.Text;
using MySql.Data.MySqlClient;
using iFileProxy.Middlewares;
+using System.Reflection;
namespace iFileProxy
{
@@ -23,9 +24,24 @@ namespace iFileProxy
CommandLineArgsHelper argsHelper = new(args);
+ // 解析命令行参数
+ CommandLineArgumentDispatcher.Parse(args);
+
+ if (argsHelper.GetBooleanValue("--version") || argsHelper.GetBooleanValue("-v"))
+ {
+ var buildTime = MasterHelper.GetBuildTime(Assembly.GetEntryAssembly());
+ StringBuilder sb = new StringBuilder();
+ sb.AppendLine(new string('=', 10));
+ sb.AppendLine($"Build DateTime:\t{buildTime}");
+ sb.AppendLine(new string('=', 10));
+
+ Console.WriteLine(sb.ToString());
+ Environment.Exit(0);
+ }
+
Console.Write(" "); // 补全日志第一行开头的空白
- var builder = WebApplication.CreateBuilder(args);
+ var builder = WebApplication.CreateBuilder();
// CORS配置
builder.Services.AddCors(options =>
@@ -81,14 +97,11 @@ namespace iFileProxy
// 初始化缓存管理服务
LocalCacheManager localCacheManager = new(app.Services);
- // 解析命令行参数
- CmdArgsHandler.ParseArgs(args, app.Services);
-
// 开启配置热重载
app.Services.GetRequiredService().EnableHotReload();
- if (!argsHelper.GetBooleanValue("disable-startup-check"))
+ if (!argsHelper.GetBooleanValue("--disable-startup-check|-D"))
// 初始化验证配置文件
AppConfig.CheckAppConfig(app.Services);
@@ -141,8 +154,8 @@ namespace iFileProxy
var dbGateService = app.Services.GetRequiredService();
SerilogConfig.CreateLogger(dbGateService, args);
- if (!argsHelper.GetStringValue("url").IsNullOrEmpty())
- app.Run(argsHelper.GetStringValue("url"));
+ if (!argsHelper.GetStringValue("--bind-url|-B").IsNullOrEmpty())
+ app.Run(argsHelper.GetStringValue("--bind-url|-B"));
else
app.Run();
}
diff --git a/src/Properties/PublishProfiles/FolderProfile.pubxml b/src/Properties/PublishProfiles/FolderProfile.pubxml
index 1296e0c..8285a16 100644
--- a/src/Properties/PublishProfiles/FolderProfile.pubxml
+++ b/src/Properties/PublishProfiles/FolderProfile.pubxml
@@ -15,7 +15,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<_TargetId>Folder
net8.0
- linux-x64
+ win-x64
e343bd8a-27ed-47e2-b50d-e3000730e65e
false
true
diff --git a/src/SerilogConfig.cs b/src/SerilogConfig.cs
index f0495e8..a6ec49a 100644
--- a/src/SerilogConfig.cs
+++ b/src/SerilogConfig.cs
@@ -26,7 +26,7 @@
var loggerConfiguration = new LoggerConfiguration();
- if (args != null && new CommandLineArgsHelper(args).GetBooleanValue("dev-logger"))
+ if (args != null && new CommandLineArgsHelper(args).GetBooleanValue("--dev-logging|-d"))
{
loggerConfiguration.MinimumLevel.Debug();
}
diff --git a/src/iFileProxy.csproj b/src/iFileProxy.csproj
index 9969e7d..4982a72 100644
--- a/src/iFileProxy.csproj
+++ b/src/iFileProxy.csproj
@@ -1,22 +1,26 @@
-
- net8.0
- enable
- enable
- true
-
+
+ net8.0
+ enable
+ enable
+ true
+
-
-
-
-
-
-
-
-
-
-
-
+
+ build$([System.DateTime]::UtcNow.ToString("yyyyMMddHHmmssZ"))
+
+
+
+
+
+
+
+
+
+
+
+
+