From e57938fbda9bff702004038f76d009422968bff5 Mon Sep 17 00:00:00 2001
From: alielie <alielie@git.com>
Date: 星期五, 06 十一月 2026 18:05:07 +0800
Subject: [PATCH] 提交代码
---
DeviceService/DriverManager/DriverLoader.cs | 784 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 784 insertions(+), 0 deletions(-)
diff --git a/DeviceService/DriverManager/DriverLoader.cs b/DeviceService/DriverManager/DriverLoader.cs
new file mode 100644
index 0000000..fa2c731
--- /dev/null
+++ b/DeviceService/DriverManager/DriverLoader.cs
@@ -0,0 +1,784 @@
+using System.IO;
+using System.Reflection;
+
+namespace DeviceService.Driver
+{
+ /// <summary>
+ /// 椹卞姩鐨勭▼搴忛泦鎻忚堪锛堣法 AppDomain 鎸夊�煎皝閫侊級銆�
+ /// 娉ㄦ剰锛氳繖浜� DTO 鍙湇鍔′簬"瀹夸富 <-> 鍔犺浇鍣�"涔嬮棿鐨勯�氫俊锛�
+ /// 椹卞姩 dll 涓嶉渶瑕佸紩鐢ㄦ湰绋嬪簭闆嗭紝涔熶笉闇�瑕佸疄鐜颁换浣曟帴鍙c��
+ /// </summary>
+ [Serializable]
+ public sealed class DriverAssemblyInfo
+ {
+ /// <summary>dll 鏂囦欢鍚�</summary>
+ public string FileName { get; set; }
+
+ /// <summary>绋嬪簭闆嗗畬鏁存爣璇嗭紙鍔犺浇鎴愬姛鏃讹級</summary>
+ public string AssemblyFullName { get; set; }
+
+ /// <summary>鍔犺浇澶辫触鍘熷洜锛堟垚鍔熸椂涓� null锛�</summary>
+ public string Error { get; set; }
+
+ /// <summary>甯� [DriverDesc] 娉ㄨВ鐨勯┍鍔ㄧ被鍨嬶紙鎸夌被鍨嬪悕鎺掑簭锛�</summary>
+ public DriverTypeInfo[] Types { get; set; }
+ }
+
+ /// <summary>
+ /// 涓�涓┍鍔ㄧ被鍨嬬殑鎻忚堪淇℃伅锛堟潵鑷� DriverDescAttribute锛夈��
+ /// 閫氳繃 (绫诲瀷, 鍝佺墝) 鍙敮涓�瀹氫綅鍒拌绫诲瀷銆�
+ /// </summary>
+ [Serializable]
+ public sealed class DriverTypeInfo
+ {
+ /// <summary>CLR 绫诲瀷鍏ㄥ悕</summary>
+ public string FullName { get; set; }
+
+ /// <summary>娉ㄨВ涓殑"绫诲瀷"锛堝 CAN銆佷覆鍙o級</summary>
+ public string DriverType { get; set; }
+
+ /// <summary>娉ㄨВ涓殑"鍝佺墝"锛堝 BA銆丅B锛�</summary>
+ public string Brand { get; set; }
+ }
+
+ /// <summary>
+ /// 椹卞姩绫诲瀷涓婄殑涓�涓叕鍏辨柟娉曘��
+ /// </summary>
+ [Serializable]
+ public sealed class DriverMethodInfo
+ {
+ /// <summary>鏂规硶鍦ㄨ绫诲瀷鏂规硶琛ㄤ腑鐨勭储寮曪紙璋冪敤鏃跺洖浼狅級</summary>
+ public int Index { get; set; }
+
+ public string Name { get; set; }
+
+ /// <summary>鍙绛惧悕锛屼緥濡� int ReadStatus(int channel)</summary>
+ public string Signature { get; set; }
+
+ public bool IsStatic { get; set; }
+
+ public int ParameterCount { get; set; }
+
+ /// <summary>鍙傛暟鍒楄〃锛堢被鍨嬪悕 + 鍙傛暟鍚嶏級锛岀敤浜庣晫闈㈡彁绀�</summary>
+ public string[] Parameters { get; set; }
+ }
+
+ /// <summary>
+ /// 鍙嶅皠璋冪敤缁撴灉銆�
+ /// </summary>
+ [Serializable]
+ public sealed class InvokeResult
+ {
+ public bool Success { get; set; }
+
+ /// <summary>杩斿洖鍊兼枃鏈紙鎴愬姛鏃讹級</summary>
+ public string Output { get; set; }
+
+ /// <summary>閿欒淇℃伅锛堝け璐ユ椂锛�</summary>
+ public string Error { get; set; }
+ }
+
+ /// <summary>
+ /// 鐩存帴璋冪敤缁撴灉锛氫繚鐣欏師濮嬭繑鍥炲�间笌 out/ref 鍥炲~鍊硷紝
+ /// 渚� RealProxy 鍔ㄦ�佷唬鐞嗘妸椹卞姩璋冪敤閫傞厤鎴愬己绫诲瀷鎺ュ彛鏂规硶銆�
+ /// 娉ㄦ剰锛歏alue / ArgsOut 鍙兘鎼哄甫鍙法鍩熷皝閫佺殑鏁版嵁锛堝熀鍏冪被鍨嬨�乻tring銆乕Serializable] DTO锛夈��
+ /// </summary>
+ [Serializable]
+ public sealed class InvokeDirectResult
+ {
+ public bool Success { get; set; }
+
+ /// <summary>鏂规硶杩斿洖鍊硷紙void 鏂规硶涓� null锛�</summary>
+ public object Value { get; set; }
+
+ /// <summary>璋冪敤鍚庣殑鍙傛暟鏁扮粍锛坥ut/ref 浣嶇疆涓哄洖濉�硷紝鍏朵綑浣嶇疆鍘熷�硷級</summary>
+ public object[] ArgsOut { get; set; }
+
+ /// <summary>閿欒淇℃伅锛堝け璐ユ椂锛�</summary>
+ public string Error { get; set; }
+ }
+
+ /// <summary>
+ /// 杩愯鍦ㄦ瘡涓┍鍔ㄥ寘涓撳睘 AppDomain 鍐呯殑鍔犺浇鍣ㄣ��
+ ///
+ /// 璁捐鍓嶆彁锛氶┍鍔� dll 鏉ヨ嚜涓嶅悓鍘傚晢锛屽郊姝ゆ病鏈変换浣曞叡鍚屾帴鍙�/鍩虹被绾﹀畾锛�
+ /// 鐢氳嚦浜掍笉鍏煎锛堝悓涓�绗笁鏂逛緷璧栫殑涓嶅悓鐗堟湰锛夈��
+ /// 鍥犳杩欓噷鍙仛閫氱敤鍙嶅皠锛氭灇涓惧叕寮�绫诲瀷銆佹灇涓惧叕鍏辨柟娉曘�佸弽灏勫垱寤哄疄渚嬨�佸弽灏勮皟鐢ㄣ��
+ ///
+ /// 璇ュ煙鐨� ApplicationBase 琚缃负鏌愪釜椹卞姩瀛愭枃浠跺す锛�
+ /// 鎵�浠ラ┍鍔ㄧ殑鍏ㄩ儴渚濊禆鍙兘浠庤嚜宸辩洰褰曡В鏋愶紝澶╃劧闅旂鐗堟湰鍐茬獊銆�
+ /// </summary>
+ public class DriverLoader : MarshalByRefObject
+ {
+ private static readonly HashSet<string> FailedAssemblies =
+ new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+
+ private readonly Dictionary<string, Type> _types = new Dictionary<string, Type>(StringComparer.Ordinal);
+ private readonly Dictionary<string, MethodInfo[]> _methodCache = new Dictionary<string, MethodInfo[]>(StringComparer.Ordinal);
+ private readonly Dictionary<Type, object> _instances = new Dictionary<Type, object>();
+
+ /// <summary>鐢� DriverManager 鍒涘缓銆佹寜鍙ユ焺绠$悊鐨勯┍鍔ㄥ疄渚�</summary>
+ private readonly Dictionary<string, ManagedInstance> _managedInstances =
+ new Dictionary<string, ManagedInstance>(StringComparer.Ordinal);
+
+ /// <summary>椹卞姩绱㈠紩锛�(绫诲瀷, 鍝佺墝) 鈫� 椹卞姩淇℃伅锛宬ey 褰㈠ "CAN|BA"</summary>
+ private readonly Dictionary<string, DriverTypeInfo> _driverIndex =
+ new Dictionary<string, DriverTypeInfo>(StringComparer.OrdinalIgnoreCase);
+
+ // 鏃犻檺鐢熷瓨鏈燂紝閬垮厤杩滅▼浠g悊琚洖鏀�
+ public override object InitializeLifetimeService() => null;
+
+ public DriverLoader()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
+ }
+
+ #region 鍙戠幇
+
+ /// <summary>
+ /// 鎵弿鏈┍鍔ㄧ洰褰曚笅鐨勬墍鏈� dll锛堝拷鐣ュ涓昏嚜韬殑 MultiPlugin.* 杩愯鏃舵枃浠讹級锛�
+ /// 杩斿洖姣忎釜绋嬪簭闆嗙殑淇℃伅涓庡叕寮�绫诲瀷鍒楄〃銆�
+ /// </summary>
+ public DriverAssemblyInfo[] LoadAssemblies()
+ {
+ var dir = AppDomain.CurrentDomain.BaseDirectory;
+ var result = new List<DriverAssemblyInfo>();
+
+ foreach (var path in Directory.GetFiles(dir, "*.dll").OrderBy(p => p, StringComparer.OrdinalIgnoreCase))
+ {
+ var fileName = Path.GetFileName(path);
+ if (fileName.StartsWith("MultiPlugin.", StringComparison.OrdinalIgnoreCase))
+ {
+ continue; // 瀹夸富鍩虹璁炬柦锛岄潪椹卞姩
+ }
+
+ var info = new DriverAssemblyInfo { FileName = fileName };
+ try
+ {
+ var assembly = Assembly.Load(Path.GetFileNameWithoutExtension(path));
+ info.AssemblyFullName = assembly.FullName;
+
+ // 鍙敹褰曞甫 [DriverDesc] 娉ㄨВ鐨勭被锛屽叾浣欑被鍨嬩竴寰嬪拷鐣�
+ var drivers = new List<DriverTypeInfo>();
+ foreach (var type in assembly.GetExportedTypes())
+ {
+ if (!type.IsClass || type.IsAbstract)
+ {
+ continue;
+ }
+
+ var desc = ReadDriverDesc(type);
+ if (desc == null)
+ {
+ continue;
+ }
+
+ _types[type.FullName] = type;
+
+ var driverInfo = new DriverTypeInfo
+ {
+ FullName = type.FullName,
+ DriverType = desc.Item1,
+ Brand = desc.Item2
+ };
+ drivers.Add(driverInfo);
+ _driverIndex[DriverKey(desc.Item1, desc.Item2)] = driverInfo;
+ }
+
+ info.Types = drivers.OrderBy(t => t.FullName, StringComparer.Ordinal).ToArray();
+ }
+ catch (Exception ex)
+ {
+ // 闈炴墭绠� dll銆佺己灏戜緷璧栥�佹灦鏋勪笉鍖归厤绛夐兘浼氬埌杩欓噷
+ info.Error = ex.Message;
+ }
+
+ result.Add(info);
+ }
+
+ return result.ToArray();
+ }
+
+ /// <summary>
+ /// 鎸� (绫诲瀷, 鍝佺墝) 鏌ユ壘椹卞姩銆備换涓�瀛楁鐣欑┖瑙嗕负閫氶厤銆�
+ /// </summary>
+ /// <returns>鍛戒腑鐨勭涓�涓┍鍔ㄤ俊鎭紱鏈懡涓繑鍥� null</returns>
+ public DriverTypeInfo FindDriver(string driverType, string brand)
+ {
+ var key = DriverKey(driverType, brand);
+ if (_driverIndex.TryGetValue(key, out var exact))
+ {
+ return exact;
+ }
+
+ // 绮剧‘鏈懡涓笖瀛樺湪閫氶厤瀛楁鏃剁嚎鎬ф壂鎻�
+ var anyType = key.StartsWith("*|", StringComparison.Ordinal);
+ var anyBrand = key.EndsWith("|*", StringComparison.Ordinal);
+ if (!anyType && !anyBrand)
+ {
+ return null;
+ }
+
+ foreach (var info in _driverIndex.Values)
+ {
+ if (!anyType && !string.Equals(info.DriverType?.Trim(), driverType?.Trim(), StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ if (!anyBrand && !string.Equals(info.Brand?.Trim(), brand?.Trim(), StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ return info;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// 鐢ㄩ腑瀛愬弽灏勮鍙� [DriverDesc] 娉ㄨВ鐨� Type/Brand 灞炴�у�笺��
+ /// 瀹夸富鍩虹璁炬柦涓嶅紩鐢� Driver.Core锛屽彧鎸�"灞炴�у悕"瑙h�﹁鍙栵紝
+ /// 杩欐牱鍘傚晢 SDK 鍗囩骇/鎹㈢増鏈笉浼氬奖鍝嶅涓汇��
+ /// </summary>
+ private static Tuple<string, string> ReadDriverDesc(Type type)
+ {
+ foreach (var attr in type.GetCustomAttributes(false))
+ {
+ var attrType = attr.GetType();
+ if (!attrType.Name.Equals("DriverDescAttribute", StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ var typeProp = attrType.GetProperty("Type");
+ var brandProp = attrType.GetProperty("Brand");
+ if (typeProp == null || brandProp == null)
+ {
+ continue;
+ }
+
+ return Tuple.Create(typeProp.GetValue(attr, null) as string,
+ brandProp.GetValue(attr, null) as string);
+ }
+
+ return null;
+ }
+
+ private static string DriverKey(string driverType, string brand)
+ {
+ var t = string.IsNullOrWhiteSpace(driverType) ? "*" : driverType.Trim().ToUpperInvariant();
+ var b = string.IsNullOrWhiteSpace(brand) ? "*" : brand.Trim().ToUpperInvariant();
+ return $"{t}|{b}";
+ }
+
+ /// <summary>
+ /// 鍒楀嚭鏌愪釜绫诲瀷鐨勫叕鍏辨柟娉曪紙灞炴�ц闂櫒浼氳杩囨护鎺夛級銆�
+ /// </summary>
+ public DriverMethodInfo[] GetMethods(string typeFullName)
+ {
+ var type = ResolveType(typeFullName);
+ if (type == null)
+ {
+ return new DriverMethodInfo[0];
+ }
+
+ return GetMethodInfos(type)
+ .Select((m, i) =>
+ {
+ var parameters = m.GetParameters();
+ return new DriverMethodInfo
+ {
+ Index = i,
+ Name = m.Name,
+ IsStatic = m.IsStatic,
+ ParameterCount = parameters.Length,
+ Signature = BuildSignature(m),
+ Parameters = parameters
+ .Select(p => $"{FormatTypeName(p.ParameterType)} {p.Name}")
+ .ToArray()
+ };
+ })
+ .ToArray();
+ }
+
+ #endregion
+
+ #region 瀹炰緥绠$悊
+
+ private sealed class ManagedInstance
+ {
+ public Type Type;
+ public object Target;
+ }
+
+ /// <summary>
+ /// 鍒涘缓椹卞姩绫诲瀷鐨勬柊瀹炰緥锛堜笉璧� Invoke 鐨勯粯璁ょ紦瀛樺疄渚嬶級锛屾寜鍙ユ焺鐧昏渚� DriverManager 绠$悊銆�
+ /// </summary>
+ public DriverInstance CreateInstance(string typeFullName, string driverType, string brand)
+ {
+ var type = ResolveType(typeFullName)
+ ?? throw new InvalidOperationException($"鏈壘鍒扮被鍨�: {typeFullName}");
+
+ var ctor = type.GetConstructor(Type.EmptyTypes)
+ ?? throw new MissingMethodException(typeFullName, ".ctor锛堢己灏戝叕鍏辨棤鍙傛瀯閫犲嚱鏁帮級");
+
+ var target = ctor.Invoke(null);
+
+ var handle = Guid.NewGuid().ToString("N");
+ _managedInstances[handle] = new ManagedInstance { Type = type, Target = target };
+
+ return new DriverInstance(this, handle, type.FullName, driverType, brand);
+ }
+
+ /// <summary>
+ /// 鍦ㄦ寚瀹氬彞鏌勭殑椹卞姩瀹炰緥涓婃寜"鍘熷瀵硅薄鍙傛暟"鐩存帴璋冪敤鏂规硶锛�
+ /// 淇濈暀鍘熷杩斿洖鍊间笌 out/ref 鍥炲~鍊硷紙渚� RealProxy 鍔ㄦ�佷唬鐞嗕娇鐢級銆�
+ /// </summary>
+ public InvokeDirectResult InvokeOnInstanceDirect(string handle, int methodIndex, object[] args)
+ {
+ var result = new InvokeDirectResult();
+ if (!_managedInstances.TryGetValue(handle, out var managed))
+ {
+ result.Success = false;
+ result.Error = $"瀹炰緥涓嶅瓨鍦ㄦ垨宸查噴鏀�: {handle}";
+ return result;
+ }
+
+ var methods = GetMethodInfos(managed.Type);
+ if (methodIndex < 0 || methodIndex >= methods.Length)
+ {
+ result.Success = false;
+ result.Error = $"鏂规硶绱㈠紩鏃犳晥: {methodIndex}锛堝叡 {methods.Length} 涓柟娉曪級";
+ return result;
+ }
+
+ try
+ {
+ var method = methods[methodIndex];
+ var parameters = method.GetParameters();
+ args = args ?? new object[0];
+
+ if (parameters.Length != args.Length)
+ {
+ result.Success = false;
+ result.Error = $"鍙傛暟鏁伴噺涓嶅尮閰�: {method.Name} 闇�瑕� {parameters.Length} 涓紝瀹為檯浼犲叆 {args.Length} 涓�";
+ return result;
+ }
+
+ var converted = new object[parameters.Length];
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ converted[i] = CoerceArg(args[i], parameters[i].ParameterType, parameters[i].Name);
+ }
+
+ result.Value = method.Invoke(managed.Target, converted);
+ result.ArgsOut = converted;
+ result.Success = true;
+ return result;
+ }
+ catch (TargetInvocationException ex)
+ {
+ var inner = ex.InnerException ?? ex;
+ result.Success = false;
+ result.Error = $"{inner.GetType().Name}: {inner.Message}";
+ return result;
+ }
+ catch (Exception ex)
+ {
+ result.Success = false;
+ result.Error = $"{ex.GetType().Name}: {ex.Message}";
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// 鍦ㄦ寚瀹氬彞鏌勭殑椹卞姩瀹炰緥涓婂弽灏勮皟鐢ㄦ柟娉曪紙瀹為檯鎵ц鍙戠敓鍦ㄩ┍鍔ㄨ嚜宸辩殑鍩熷唴锛夈��
+ /// </summary>
+ public InvokeResult InvokeOnInstance(string handle, int methodIndex, string[] rawArgs)
+ {
+ if (!_managedInstances.TryGetValue(handle, out var managed))
+ {
+ return Fail($"瀹炰緥涓嶅瓨鍦ㄦ垨宸查噴鏀�: {handle}");
+ }
+
+ var methods = GetMethodInfos(managed.Type);
+ if (methodIndex < 0 || methodIndex >= methods.Length)
+ {
+ return Fail($"鏂规硶绱㈠紩鏃犳晥: {methodIndex}锛堝叡 {methods.Length} 涓柟娉曪級");
+ }
+
+ return ExecuteMethod(methods[methodIndex], managed.Target, rawArgs);
+ }
+
+ /// <summary>
+ /// 閲婃斁鎸囧畾鍙ユ焺鐨勫疄渚嬶紱椹卞姩瀹炵幇 IDisposable 鏃朵細璋冪敤 Dispose銆�
+ /// </summary>
+ public void ReleaseInstance(string handle)
+ {
+ if (!_managedInstances.TryGetValue(handle, out var managed))
+ {
+ return;
+ }
+
+ _managedInstances.Remove(handle);
+ (managed.Target as IDisposable)?.Dispose();
+ }
+
+ #endregion
+
+ #region 璋冪敤
+
+ /// <summary>
+ /// 鍙嶅皠璋冪敤鎸囧畾绫诲瀷鐨勬柟娉曘��
+ /// 瀹炰緥鏂规硶浼氳嚜鍔ㄧ敤鍏叡鏃犲弬鏋勯�犲嚱鏁板垱寤猴紙骞剁紦瀛橈級瀹炰緥锛�
+ /// 闈欐�佹柟娉曟棤闇�瀹炰緥銆傞渶瑕侀暱鏈熸寔鏈夊疄渚嬭浣跨敤 <see cref="CreateInstance"/>銆�
+ /// </summary>
+ /// <param name="rawArgs">瀛楃涓插舰寮忕殑瀹炲弬锛岀敱 <see cref="ConvertArg"/> 鎸夌洰鏍囧弬鏁扮被鍨嬭浆鎹�</param>
+ public InvokeResult Invoke(string typeFullName, int methodIndex, string[] rawArgs)
+ {
+ try
+ {
+ var type = ResolveType(typeFullName);
+ if (type == null)
+ {
+ return Fail($"鏈壘鍒扮被鍨�: {typeFullName}");
+ }
+
+ var methods = GetMethodInfos(type);
+ if (methodIndex < 0 || methodIndex >= methods.Length)
+ {
+ return Fail($"鏂规硶绱㈠紩鏃犳晥: {methodIndex}锛堝叡 {methods.Length} 涓柟娉曪級");
+ }
+
+ var method = methods[methodIndex];
+
+ object target = null;
+ if (!method.IsStatic)
+ {
+ target = GetOrCreateInstance(type);
+ if (target == null)
+ {
+ return Fail($"鏃犳硶瀹炰緥鍖� {type.FullName}: 缂哄皯鍏叡鏃犲弬鏋勯�犲嚱鏁般�傚彲鏀逛负鍙皟鐢ㄨ绫诲瀷鐨勯潤鎬佹柟娉曘��");
+ }
+ }
+
+ return ExecuteMethod(method, target, rawArgs);
+ }
+ catch (TargetInvocationException ex)
+ {
+ // 椹卞姩鍐呴儴鎶涘嚭鐨勫紓甯�
+ var inner = ex.InnerException ?? ex;
+ return Fail($"{inner.GetType().Name}: {inner.Message}");
+ }
+ catch (Exception ex)
+ {
+ return Fail($"{ex.GetType().Name}: {ex.Message}");
+ }
+ }
+
+ /// <summary>
+ /// 鍙傛暟杞崲 鈫� 鍙嶅皠璋冪敤 鈫� 姹囨�昏繑鍥炲�间笌 out/ref 鍥炲~鍊笺��
+ /// </summary>
+ private static InvokeResult ExecuteMethod(MethodInfo method, object target, string[] rawArgs)
+ {
+ try
+ {
+ var parameters = method.GetParameters();
+ rawArgs = rawArgs ?? new string[0];
+
+ if (parameters.Length != rawArgs.Length)
+ {
+ return Fail($"鍙傛暟鏁伴噺涓嶅尮閰�: {method.Name} 闇�瑕� {parameters.Length} 涓弬鏁帮紝瀹為檯浼犲叆 {rawArgs.Length} 涓�");
+ }
+
+ var args = new object[parameters.Length];
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ args[i] = ConvertArg(rawArgs[i], parameters[i].ParameterType, parameters[i].Name);
+ }
+
+ var returnValue = method.Invoke(target, args);
+
+ // 姹囨�昏繑鍥炲�间笌 out/ref 鍥炲~鍊硷紙濡� Open(out string msg) 鐨� msg锛�
+ var parts = new List<string>();
+ if (method.ReturnType != typeof(void))
+ {
+ parts.Add($"杩斿洖: {Format(returnValue)}");
+ }
+
+ for (var i = 0; i < parameters.Length; i++)
+ {
+ if (parameters[i].ParameterType.IsByRef)
+ {
+ parts.Add($"{parameters[i].Name} = {Format(args[i])}");
+ }
+ }
+
+ return new InvokeResult { Success = true, Output = parts.Count == 0 ? "null" : string.Join("; ", parts) };
+ }
+ catch (TargetInvocationException ex)
+ {
+ // 椹卞姩鍐呴儴鎶涘嚭鐨勫紓甯�
+ var inner = ex.InnerException ?? ex;
+ return Fail($"{inner.GetType().Name}: {inner.Message}");
+ }
+ catch (Exception ex)
+ {
+ return Fail($"{ex.GetType().Name}: {ex.Message}");
+ }
+ }
+
+ private object GetOrCreateInstance(Type type)
+ {
+ if (_instances.TryGetValue(type, out var existing))
+ {
+ return existing;
+ }
+
+ if (type.IsAbstract || type.IsInterface)
+ {
+ return null;
+ }
+
+ var ctor = type.GetConstructor(Type.EmptyTypes);
+ if (ctor == null)
+ {
+ return null;
+ }
+
+ var instance = ctor.Invoke(null);
+ _instances[type] = instance;
+ return instance;
+ }
+
+ #endregion
+
+ #region 杈呭姪
+
+ private Type ResolveType(string typeFullName)
+ {
+ if (_types.TryGetValue(typeFullName, out var type))
+ {
+ return type;
+ }
+
+ // 鍏滃簳锛氬湪宸插姞杞界殑椹卞姩绋嬪簭闆嗛噷鏌ユ壘
+ type = AppDomain.CurrentDomain.GetAssemblies()
+ .Where(a => !a.IsDynamic)
+ .Select(a => a.GetType(typeFullName))
+ .FirstOrDefault(t => t != null);
+
+ if (type != null)
+ {
+ _types[typeFullName] = type;
+ }
+
+ return type;
+ }
+
+ private MethodInfo[] GetMethodInfos(Type type)
+ {
+ if (_methodCache.TryGetValue(type.FullName, out var cached))
+ {
+ return cached;
+ }
+
+ var methods = type
+ .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
+ .Where(m => !m.IsSpecialName) // 杩囨护 get_/set_/add_/remove_ 绛�
+ .ToArray();
+
+ _methodCache[type.FullName] = methods;
+ return methods;
+ }
+
+ private static string BuildSignature(MethodInfo method)
+ {
+ var parameters = method.GetParameters()
+ .Select(p => $"{FormatTypeName(p.ParameterType)} {p.Name}");
+
+ return $"{(method.IsStatic ? "static " : string.Empty)}{FormatTypeName(method.ReturnType)} "
+ + $"{method.Name}({string.Join(", ", parameters)})";
+ }
+
+ private static string FormatTypeName(Type type)
+ {
+ if (!type.IsGenericType)
+ {
+ return type.Name;
+ }
+
+ var name = type.Name.Substring(0, type.Name.IndexOf('`'));
+ var args = string.Join(", ", type.GetGenericArguments().Select(FormatTypeName));
+ return $"{name}<{args}>";
+ }
+
+ /// <summary>
+ /// 鎶婅法鍩熶唬鐞嗕紶鏉ョ殑瀵硅薄鍙傛暟閫傞厤涓虹洰鏍囧弬鏁扮被鍨嬶細
+ /// 绫诲瀷鍏煎鐩存帴鐢紝鍚﹀垯閫�鍖栦负瀛楃涓茶浆鎹紙楦瓙寮忓鏉惧尮閰嶏級銆�
+ /// </summary>
+ private static object CoerceArg(object arg, Type targetType, string parameterName)
+ {
+ if (targetType.IsByRef)
+ {
+ targetType = targetType.GetElementType();
+ }
+
+ if (arg == null)
+ {
+ return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
+ }
+
+ if (targetType.IsInstanceOfType(arg))
+ {
+ return arg;
+ }
+
+ return ConvertArg(arg.ToString(), targetType, parameterName);
+ }
+
+ /// <summary>
+ /// 鎶� UI 浼犳潵鐨勫瓧绗︿覆杞崲涓虹洰鏍囧弬鏁扮被鍨嬨��
+ /// 鏀寔甯哥敤鍩哄厓绫诲瀷銆佹灇涓俱�丟uid銆丏ateTime銆佸瓧绗︿覆鏁扮粍锛堜互鍒嗗彿鍒嗛殧锛夈��
+ /// </summary>
+ private static object ConvertArg(string raw, Type targetType, string parameterName)
+ {
+ raw = raw ?? string.Empty;
+
+ // out/ref 鍙傛暟瀹為檯鎸夊叾鍏冪礌绫诲瀷杞崲锛堣皟鐢ㄥ悗鐢� CLR 鍥炲~锛�
+ if (targetType.IsByRef)
+ {
+ targetType = targetType.GetElementType();
+ }
+
+ if (targetType == typeof(string) || targetType == typeof(object))
+ {
+ return raw;
+ }
+
+ if (raw.Length == 0 && !targetType.IsValueType)
+ {
+ return null;
+ }
+
+ if (targetType == typeof(bool)) return bool.Parse(raw);
+ if (targetType == typeof(char)) return raw[0];
+ if (targetType == typeof(byte)) return byte.Parse(raw);
+ if (targetType == typeof(sbyte)) return sbyte.Parse(raw);
+ if (targetType == typeof(short)) return short.Parse(raw);
+ if (targetType == typeof(ushort)) return ushort.Parse(raw);
+ if (targetType == typeof(int)) return int.Parse(raw);
+ if (targetType == typeof(uint)) return uint.Parse(raw);
+ if (targetType == typeof(long)) return long.Parse(raw);
+ if (targetType == typeof(ulong)) return ulong.Parse(raw);
+ if (targetType == typeof(float)) return float.Parse(raw);
+ if (targetType == typeof(double)) return double.Parse(raw);
+ if (targetType == typeof(decimal)) return decimal.Parse(raw);
+ if (targetType == typeof(Guid)) return Guid.Parse(raw);
+ if (targetType == typeof(DateTime)) return DateTime.Parse(raw);
+ if (targetType.IsEnum) return Enum.Parse(targetType, raw, true);
+
+ if (targetType.IsArray)
+ {
+ var elementType = targetType.GetElementType();
+ var parts = raw.Length == 0 ? new string[0] : raw.Split(';');
+ var array = Array.CreateInstance(elementType, parts.Length);
+ for (var i = 0; i < parts.Length; i++)
+ {
+ array.SetValue(ConvertArg(parts[i], elementType, parameterName), i);
+ }
+
+ return array;
+ }
+
+ throw new InvalidOperationException(
+ $"鍙傛暟 {parameterName} 鐨勭被鍨� {targetType.Name} 鏆備笉鏀寔浠庡瓧绗︿覆杞崲锛堟敮鎸侊細瀛楃涓层�佹暟瀛椼�乥ool銆佹灇涓俱�丟uid銆丏ateTime銆佹暟缁勶級");
+ }
+
+ private static string Format(object value)
+ {
+ if (value == null)
+ {
+ return "null";
+ }
+
+ if (value is string text)
+ {
+ return Truncate(text);
+ }
+
+ if (value is Array array)
+ {
+ var items = array.Cast<object>().Select(x => x == null ? "null" : x.ToString());
+ return Truncate($"[{string.Join(", ", items)}]");
+ }
+
+ return Truncate(value.ToString());
+ }
+
+ private static string Truncate(string text)
+ {
+ const int max = 4000;
+ return text.Length <= max ? text : text.Substring(0, max) + " ...(宸叉埅鏂�)";
+ }
+
+ private static InvokeResult Fail(string message) => new InvokeResult { Success = false, Error = message };
+
+ /// <summary>
+ /// 渚濊禆瑙f瀽鍏滃簳锛氬彧鍦ㄦ湰椹卞姩鐩綍锛堝強鍔犺浇鍣ㄦ墍鍦ㄧ洰褰曪級鍐呮煡鎵撅紝
+ /// 淇濊瘉涓嶄細涓插埌鍏朵粬椹卞姩鍖呯殑鍚屽悕绋嬪簭闆嗐��
+ /// </summary>
+ private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ var simpleName = new AssemblyName(args.Name).Name;
+ if (FailedAssemblies.Contains(simpleName))
+ {
+ return null;
+ }
+
+ var dirs = new List<string>();
+
+ // 浼樺厛鎸夊姞杞藉櫒鎵�鍦ㄧ洰褰曪紙瀹夸富 bin锛夎В鏋愬涓诲熀纭�璁炬柦锛屽啀鍏滃簳椹卞姩鐩綍
+ var loaderLocation = typeof(DriverLoader).Assembly.Location;
+ var loaderDir = string.IsNullOrEmpty(loaderLocation) ? null : Path.GetDirectoryName(loaderLocation);
+ if (!string.IsNullOrEmpty(loaderDir))
+ {
+ dirs.Add(loaderDir);
+ }
+
+ var baseDir = AppDomain.CurrentDomain.BaseDirectory;
+ if (!dirs.Contains(baseDir))
+ {
+ dirs.Add(baseDir);
+ }
+
+ foreach (var dir in dirs)
+ {
+ foreach (var ext in new[] { ".dll", ".exe" })
+ {
+ var candidate = Path.Combine(dir, simpleName + ext);
+ if (!File.Exists(candidate))
+ {
+ continue;
+ }
+
+ try
+ {
+ return Assembly.LoadFrom(candidate);
+ }
+ catch
+ {
+ // 灏濊瘯涓嬩竴涓�欓��
+ }
+ }
+ }
+
+ FailedAssemblies.Add(simpleName);
+ return null;
+ }
+
+ #endregion
+ }
+}
--
Gitblit v1.9.1