// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.Loader; using SysReflection = System.Reflection.IntrospectionExtensions; namespace Admin.NET.Core; /// /// 反射帮助类 /// 提供程序集、类型、属性等反射操作的工具方法 /// public static class ReflectionHelper { #region 程序集 /// /// 获取应用程序的入口程序集 /// /// 入口程序集,如果无法确定则返回 null public static Assembly? GetEntryAssembly() { return Assembly.GetEntryAssembly(); } /// /// 获取入口程序集的名称 /// /// 程序集名称,如果无法获取则返回 null public static string? GetEntryAssemblyName() { return GetEntryAssembly()?.GetName().Name; } /// /// 获取入口程序集的版本信息 /// /// 程序集版本,如果无法获取则返回 null public static Version? GetEntryAssemblyVersion() { return GetEntryAssembly()?.GetName().Version; } /// /// 获取指定目录下的程序集文件路径 /// /// 要搜索的文件夹路径 /// 搜索选项(是否包含子目录) /// 程序集文件路径集合(.dll 和 .exe 文件) /// 当文件夹路径为空或 null 时 public static IEnumerable GetAssemblyFiles(string folderPath, SearchOption searchOption) { ArgumentException.ThrowIfNullOrWhiteSpace(folderPath); return Directory .EnumerateFiles(folderPath, "*.*", searchOption) .Where(s => s.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) || s.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)); } /// /// 从指定目录加载所有程序集 /// /// 要搜索的文件夹路径 /// 搜索选项(是否包含子目录) /// 加载的程序集列表 /// 当文件夹路径为空或 null 时 public static List LoadAssemblies(string folderPath, SearchOption searchOption) { ArgumentException.ThrowIfNullOrWhiteSpace(folderPath); return [.. GetAssemblyFiles(folderPath, searchOption).Select(AssemblyLoadContext.Default.LoadFromAssemblyPath)]; } /// /// 获取当前应用程序域中加载的所有程序集 /// /// 已加载的程序集集合 public static IEnumerable GetAllAssemblies() { return AssemblyLoadContext.Default.Assemblies; } /// /// 获取所有被引用的程序集(递归获取所有依赖项) /// /// 是否跳过系统程序集(默认为 true) /// 被引用的程序集集合 public static IEnumerable GetAllReferencedAssemblies(bool skipSystemAssemblies = true) { var rootAssembly = Assembly.GetEntryAssembly(); rootAssembly ??= Assembly.GetCallingAssembly(); HashSet returnAssemblies = new(new AssemblyEquality()); HashSet loadedAssemblies = []; Queue assembliesToCheck = new(); assembliesToCheck.Enqueue(rootAssembly); if (skipSystemAssemblies && IsSystemAssembly(rootAssembly)) { if (IsValid(rootAssembly)) { _ = returnAssemblies.Add(rootAssembly); } } while (assembliesToCheck.Count != 0) { var assemblyToCheck = assembliesToCheck.Dequeue(); foreach (var reference in assemblyToCheck.GetReferencedAssemblies()) { if (loadedAssemblies.Contains(reference.FullName)) { continue; } var assembly = Assembly.Load(reference); if (skipSystemAssemblies && IsSystemAssembly(assembly)) { continue; } assembliesToCheck.Enqueue(assembly); _ = loadedAssemblies.Add(reference.FullName); if (IsValid(assembly)) { _ = returnAssemblies.Add(assembly); } } } var asmsInBaseDir = Directory.EnumerateFiles(AppContext.BaseDirectory, "*.dll", new EnumerationOptions { RecurseSubdirectories = true }); foreach (var assemblyPath in asmsInBaseDir) { if (!IsManagedAssembly(assemblyPath)) { continue; } var asmName = AssemblyName.GetAssemblyName(assemblyPath); // 如果程序集已经加载过了就不再加载 if (returnAssemblies.Any(x => AssemblyName.ReferenceMatchesDefinition(x.GetName(), asmName))) { continue; } if (skipSystemAssemblies && IsSystemAssembly(assemblyPath)) { continue; } var asm = TryLoadAssembly(assemblyPath); if (asm is null) { continue; } if (!IsValid(asm)) { continue; } if (skipSystemAssemblies && IsSystemAssembly(asm)) { continue; } _ = returnAssemblies.Add(asm); } return [.. returnAssemblies]; } /// /// 获取符合条件名称的程序集 /// /// 前缀名 /// 后缀名 /// 包含名 /// public static IEnumerable GetEffectiveAssemblies(string prefix, string suffix, string contain) { ArgumentException.ThrowIfNullOrWhiteSpace(prefix); ArgumentException.ThrowIfNullOrWhiteSpace(suffix); ArgumentException.ThrowIfNullOrWhiteSpace(contain); return GetAllAssemblies() .Where(assembly => assembly.ManifestModule.Name.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase)) .Where(assembly => assembly.ManifestModule.Name.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) .Where(assembly => assembly.ManifestModule.Name.Contains(contain, StringComparison.InvariantCultureIgnoreCase)) .Distinct(); } /// /// 获取符合条件前后缀名称的程序集 /// /// 前缀名 /// 后缀名 /// public static IEnumerable GetEffectivePatchAssemblies(string prefix, string suffix) { ArgumentException.ThrowIfNullOrWhiteSpace(prefix); ArgumentException.ThrowIfNullOrWhiteSpace(suffix); return GetAllAssemblies() .Where(assembly => assembly.ManifestModule.Name.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase)) .Where(assembly => assembly.ManifestModule.Name.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) .Distinct(); } /// /// 获取符合条件包含名称的程序集 /// /// 包含名 /// public static IEnumerable GetEffectiveCenterAssemblies(string contain) { ArgumentException.ThrowIfNullOrWhiteSpace(contain); return GetAllAssemblies() .Where(assembly => assembly.ManifestModule.Name.Contains(contain, StringComparison.InvariantCultureIgnoreCase)) .Distinct(); } /// /// 获取框架程序集 /// /// public static IEnumerable GetAdminNETAssemblies() { return GetEffectivePatchAssemblies("Admin.NET", "dll"); } /// /// 获取应用程序集 /// /// public static IEnumerable GetApplicationAssemblies() { return GetEffectiveCenterAssemblies("Application"); } /// /// 获取框架应用程序集 /// /// public static IEnumerable GetAdminNETApplicationAssemblies() { return GetEffectiveAssemblies("Admin.NET", "dll", "Application"); } #endregion 程序集 #region 程序集类 /// /// 获取所有已加载程序集中的所有类型 /// /// 所有类型的集合 public static IEnumerable GetAllTypes() { return GetAllAssemblies() .SelectMany(GetAllTypes) .Distinct(); } /// /// 获取指定程序集中的所有类型(安全获取,处理加载异常) /// /// 目标程序集 /// 程序集中的类型集合 /// 当程序集为 null 时 public static IEnumerable GetAllTypes(Assembly assembly) { ArgumentNullException.ThrowIfNull(assembly); try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where(type => type != null)!; } } /// /// 获取框架框架程序集中的所有类型 /// /// 框架框架类型集合 public static IEnumerable GetAdminNETTypes() { return GetAdminNETAssemblies() .SelectMany(GetAllTypes) .Distinct(); } /// /// 获取应用程序集中的所有类型 /// /// 应用程序类型集合 public static IEnumerable GetApplicationTypes() { return GetApplicationAssemblies() .SelectMany(GetAllTypes) .Distinct(); } /// /// 获取框架应用程序集中的所有类型 /// /// 框架应用程序类型集合 public static IEnumerable GetAdminNETApplicationTypes() { return GetAdminNETApplicationAssemblies() .SelectMany(GetAllTypes) .Distinct(); } #endregion 程序集类 #region 类型 /// /// 检查给定类型是否实现或继承了指定的泛型类型 /// /// 要检查的类型 /// 泛型类型定义 /// 如果给定类型实现或继承了泛型类型则返回 true,否则返回 false public static bool IsAssignableToGenericType(Type givenType, Type genericType) { ArgumentNullException.ThrowIfNull(givenType); ArgumentNullException.ThrowIfNull(genericType); var givenTypeInfo = SysReflection.GetTypeInfo(givenType); if (givenTypeInfo.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) { return true; } foreach (var interfaceType in givenTypeInfo.GetInterfaces()) { if (SysReflection.GetTypeInfo(interfaceType).IsGenericType && interfaceType.GetGenericTypeDefinition() == genericType) { return true; } } return givenTypeInfo.BaseType != null && IsAssignableToGenericType(givenTypeInfo.BaseType, genericType); } /// /// 获取给定类型实现的所有泛型类型 /// /// 要检查的类型 /// 泛型类型定义 /// 实现的泛型类型列表 public static List GetImplementedGenericTypes(Type givenType, Type genericType) { ArgumentNullException.ThrowIfNull(givenType); ArgumentNullException.ThrowIfNull(genericType); var result = new List(); AddImplementedGenericTypes(result, givenType, genericType); return result; } /// /// 尝试获取类成员及其声明类型上定义的单个特性,包括继承的特性 /// 如果未找到则返回默认值 /// /// 特性类型 /// 成员信息 /// 默认值(默认为 null) /// 是否从基类继承特性 /// 找到的特性实例或默认值 public static TAttribute? GetSingleAttributeOrDefault(MemberInfo memberInfo, TAttribute? defaultValue = default, bool inherit = true) where TAttribute : Attribute { ArgumentNullException.ThrowIfNull(memberInfo); // 使用 GetCustomAttributes 方法获取特性 return memberInfo.IsDefined(typeof(TAttribute), inherit) ? memberInfo.GetCustomAttributes(typeof(TAttribute), inherit).Cast().First() : defaultValue; } /// /// 尝试获取类成员或其声明类型上定义的单个特性,包括继承的特性 /// 如果未找到则返回默认值 /// /// 特性类型 /// 成员信息 /// 默认值(默认为 null) /// 是否从基类继承特性 /// 找到的特性实例或默认值 public static TAttribute? GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(MemberInfo memberInfo, TAttribute? defaultValue = default, bool inherit = true) where TAttribute : class { ArgumentNullException.ThrowIfNull(memberInfo); return memberInfo.GetCustomAttributes(inherit).OfType().FirstOrDefault() ?? SysReflection.GetTypeInfo(memberInfo.DeclaringType).GetCustomAttributes(inherit).OfType().FirstOrDefault() ?? defaultValue; } /// /// 获取类成员及其声明类型上定义的所有特性,包括继承的特性 /// /// 特性类型 /// 成员信息 /// 是否从基类继承特性 /// 特性集合 public static IEnumerable GetAttributesOfMemberOrDeclaringType(MemberInfo memberInfo, bool inherit = true) where TAttribute : class { ArgumentNullException.ThrowIfNull(memberInfo); var customAttributes = memberInfo.GetCustomAttributes(inherit).OfType(); var declaringTypeCustomAttributes = SysReflection.GetTypeInfo(memberInfo.DeclaringType).GetCustomAttributes(inherit).OfType(); return declaringTypeCustomAttributes != null ? customAttributes.Concat(declaringTypeCustomAttributes).Distinct() : customAttributes; } /// /// 通过完整属性路径从给定对象获取属性值 /// /// 目标对象 /// 对象类型 /// 属性路径(支持嵌套属性,用点分隔) /// 属性值,如果属性不存在则返回 null public static object? GetValueByPath(object obj, Type objectType, string propertyPath) { ArgumentNullException.ThrowIfNull(obj); ArgumentNullException.ThrowIfNull(objectType); ArgumentException.ThrowIfNullOrWhiteSpace(propertyPath); var value = obj; var currentType = objectType; var objectPath = currentType.FullName; var absolutePropertyPath = propertyPath; if (objectPath != null && absolutePropertyPath.StartsWith(objectPath)) { absolutePropertyPath = absolutePropertyPath.Replace(objectPath + ".", ""); } foreach (var propertyName in absolutePropertyPath.Split('.')) { var property = currentType.GetProperty(propertyName); if (property != null) { if (value != null) { value = property.GetValue(value, null); } currentType = property.PropertyType; } else { value = null; break; } } return value; } /// /// 递归获取指定类型中的所有公共常量值(包括基类型) /// /// 目标类型 /// 常量值数组 public static string[] GetPublicConstantsRecursively(Type type) { ArgumentNullException.ThrowIfNull(type); const int MaxRecursiveParameterValidationDepth = 8; var publicConstants = new List(); static void Recursively(List constants, Type targetType, int currentDepth) { if (currentDepth > MaxRecursiveParameterValidationDepth) { return; } constants.AddRange(targetType.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) .Where(x => x.IsLiteral && !x.IsInitOnly) .Select(x => x.GetValue(null)!.ToString()!)); var nestedTypes = targetType.GetNestedTypes(BindingFlags.Public); foreach (var nestedType in nestedTypes) { Recursively(constants, nestedType, currentDepth + 1); } } Recursively(publicConstants, type, 1); return [.. publicConstants]; } /// /// 通过完整属性路径设置给定对象的属性值 /// /// 目标对象 /// 对象类型 /// 属性路径(支持嵌套属性,用点分隔) /// 要设置的值 internal static void SetValueByPath(object obj, Type objectType, string propertyPath, object value) { ArgumentNullException.ThrowIfNull(obj); ArgumentNullException.ThrowIfNull(objectType); ArgumentException.ThrowIfNullOrWhiteSpace(propertyPath); var currentType = objectType; PropertyInfo property; var objectPath = currentType.FullName!; var absolutePropertyPath = propertyPath; if (absolutePropertyPath.StartsWith(objectPath)) { absolutePropertyPath = absolutePropertyPath.Replace(objectPath + ".", ""); } var properties = absolutePropertyPath.Split('.'); if (properties.Length == 1) { property = objectType.GetProperty(properties.First())!; property.SetValue(obj, value); return; } for (var i = 0; i < properties.Length - 1; i++) { property = currentType.GetProperty(properties[i])!; obj = property.GetValue(obj, null)!; currentType = property.PropertyType; } property = currentType.GetProperty(properties.Last())!; property.SetValue(obj, value); } /// /// 添加实现的泛型类型到结果列表 /// /// 结果列表 /// 给定类型 /// 泛型类型 private static void AddImplementedGenericTypes(List result, Type givenType, Type genericType) { var givenTypeInfo = SysReflection.GetTypeInfo(givenType); if (givenTypeInfo.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) { result.AddIfNotContains(givenType); } foreach (var interfaceType in givenTypeInfo.GetInterfaces()) { if (SysReflection.GetTypeInfo(interfaceType).IsGenericType && interfaceType.GetGenericTypeDefinition() == genericType) { result.AddIfNotContains(interfaceType); } } if (givenTypeInfo.BaseType == null) { return; } AddImplementedGenericTypes(result, givenTypeInfo.BaseType, genericType); } #endregion 类型 #region 获取包含有某特性的类 /// /// 获取包含有某特性的类 /// 第一种实现 /// /// /// public static IEnumerable GetContainsAttributeTypes() where TAttribute : Attribute { return GetAllTypes() .Where(e => e.CustomAttributes.Any(g => g.AttributeType == typeof(TAttribute))); } /// /// 获取包含有某特性的类 /// 第二种实现 /// /// /// public static IEnumerable GetContainsAttributeTypes(Attribute attribute) { return GetAllTypes() .Where(e => e.CustomAttributes.Any(g => g.AttributeType == attribute.GetType())); } #endregion 获取包含有某特性的类 #region 获取不包含有某特性的类 /// /// 获取不包含有某特性的类 /// 第一种实现 /// /// /// public static IEnumerable GetFilterAttributeTypes() where TAttribute : Attribute { return GetAllTypes() .Where(e => e.CustomAttributes.All(g => g.AttributeType != typeof(TAttribute))); } /// /// 获取包含有某特性的类 /// 第二种实现 /// /// /// public static IEnumerable GetFilterAttributeTypes(Attribute attribute) { return GetAllTypes() .Where(e => e.CustomAttributes.All(g => g.AttributeType != attribute.GetType())); } #endregion 获取不包含有某特性的类 #region 获取某类的子类(非抽象类) /// /// 获取某类的子类(非抽象类) /// 第一种实现 /// /// /// public static IEnumerable GetSubClasses() where T : class { return GetAllTypes() .Where(t => t is { IsInterface: false, IsClass: true, IsAbstract: false }) .Where(t => typeof(T).IsAssignableFrom(t)); } /// /// 获取某类的子类(非抽象类) /// 第二种实现 /// /// /// public static IEnumerable GetSubClasses(Type type) { return GetAllTypes() .Where(t => t is { IsInterface: false, IsClass: true, IsAbstract: false }) .Where(type.IsAssignableFrom); } /// /// 获取某泛型接口的子类(非抽象类) /// /// /// public static IEnumerable GetSubClassesByGenericInterface(Type interfaceType) { return [.. GetAllTypes() .Where(type => type is { IsInterface: false, IsClass: true, IsAbstract: false } && type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == interfaceType))]; } #endregion 获取某类的子类(非抽象类) #region 获取继承自某类的包含有某特性的接口、类的子类(非抽象类) /// /// 获取继承自某类的包含有某特性的接口、类的子类(非抽象类) /// 第一种实现 /// /// /// /// public static IEnumerable GetContainsAttributeSubClasses() where T : class where TAttribute : Attribute { return GetSubClasses().Intersect(GetContainsAttributeTypes()); } /// /// 获取继承自某类的包含有某特性的接口、类的子类(非抽象类) /// 第二种实现 /// /// /// /// public static IEnumerable GetContainsAttributeSubClasses(Type type) where TAttribute : Attribute { return GetSubClasses(type).Intersect(GetContainsAttributeTypes()); } #endregion 获取继承自某类的包含有某特性的接口、类的子类(非抽象类) #region 获取继承自某类的不包含有某特性的接口、类的子类(非抽象类) /// /// 获取继承自某类的不包含有某特性的接口、类的子类(非抽象类) /// 第一种实现 /// /// /// /// public static IEnumerable GetFilterAttributeSubClass() where T : class where TAttribute : Attribute { return GetSubClasses().Intersect(GetFilterAttributeTypes()); } /// /// 获取继承自某类的不包含有某特性的接口、类的子类(非抽象类) /// 第二种实现 /// /// /// /// public static IEnumerable GetFilterAttributeSubClass(Type type) where TAttribute : Attribute { return GetSubClasses(type).Intersect(GetFilterAttributeTypes()); } #endregion 获取继承自某类的不包含有某特性的接口、类的子类(非抽象类) #region 程序集依赖包 /// /// 获取当前应用程序的 NuGet 程序包依赖项 /// /// 前缀名 /// NuGet 包信息列表 public static List GetNuGetPackages(string prefix) { var nugetPackages = new Dictionary(); // 获取当前应用所有程序集 var assemblies = GetEffectivePatchAssemblies(prefix, "dll"); // 查找被引用程序集中的 NuGet 库依赖项 foreach (var assembly in assemblies) { try { var referencedAssemblies = assembly.GetReferencedAssemblies() .Where(s => !s.FullName.StartsWith("Microsoft", StringComparison.OrdinalIgnoreCase) && !s.FullName.StartsWith("System", StringComparison.OrdinalIgnoreCase)) .Where(s => !string.IsNullOrEmpty(s.Name) && s.Version != null); foreach (var referencedAssembly in referencedAssemblies) { // 检查引用的程序集是否来自 NuGet if (string.IsNullOrEmpty(referencedAssembly.Name) || referencedAssembly.Version == null) { continue; } var packageName = referencedAssembly.Name; var packageVersion = referencedAssembly.Version.ToString(); // 避免重复添加相同的 NuGet 包,保留版本更高的 if (!nugetPackages.TryGetValue(packageName, out var value)) { nugetPackages[packageName] = new NuGetPackage { PackageName = packageName, PackageVersion = packageVersion }; } else { var existingVersion = Version.Parse(value.PackageVersion); var currentVersion = referencedAssembly.Version; if (currentVersion > existingVersion) { nugetPackages[packageName] = new NuGetPackage { PackageName = packageName, PackageVersion = packageVersion }; } } } } catch (Exception ex) { Debug.WriteLine($"Error processing assembly {assembly.FullName}: {ex.Message}"); } } return [.. nugetPackages.Values.OrderBy(p => p.PackageName)]; } #endregion 程序集依赖包 #region 私有方法 /// /// 判断程序集是否为系统程序集(如微软官方程序集) /// /// 要检查的程序集 /// 如果是系统程序集则返回 true,否则返回 false private static bool IsSystemAssembly(Assembly assembly) { ArgumentNullException.ThrowIfNull(assembly); var asmCompanyAttr = assembly.GetCustomAttribute(); if (asmCompanyAttr is null) { return false; } var companyName = asmCompanyAttr.Company; return companyName.Contains("Microsoft", StringComparison.OrdinalIgnoreCase); } /// /// 通过程序集路径判断是否为系统程序集 /// /// 程序集文件路径 /// 如果是系统程序集则返回 true,否则返回 false private static bool IsSystemAssembly(string assemblyPath) { ArgumentException.ThrowIfNullOrWhiteSpace(assemblyPath); try { var assembly = Assembly.LoadFrom(assemblyPath); return IsSystemAssembly(assembly); } catch { return false; } } /// /// 判断程序集是否有效(能否正常加载类型) /// /// 要验证的程序集 /// 如果程序集有效则返回 true,否则返回 false private static bool IsValid(Assembly assembly) { ArgumentNullException.ThrowIfNull(assembly); try { _ = assembly.GetTypes(); _ = assembly.DefinedTypes.ToList(); return true; } catch (ReflectionTypeLoadException) { return false; } catch (Exception) { return false; } } /// /// 判断指定文件是否为托管程序集 /// /// 程序集文件路径 /// 如果是托管程序集则返回 true,否则返回 false private static bool IsManagedAssembly(string file) { ArgumentException.ThrowIfNullOrWhiteSpace(file); try { using var fs = File.OpenRead(file); using PEReader peReader = new(fs); return peReader.HasMetadata && peReader.GetMetadataReader().IsAssembly; } catch { return false; } } /// /// 安全地尝试加载程序集,处理各种加载异常 /// /// 程序集文件路径 /// 成功加载的程序集,失败则返回 null private static Assembly? TryLoadAssembly(string assemblyPath) { ArgumentException.ThrowIfNullOrWhiteSpace(assemblyPath); if (!File.Exists(assemblyPath)) { return null; } Assembly? assembly = null; try { var assemblyName = AssemblyName.GetAssemblyName(assemblyPath); assembly = Assembly.Load(assemblyName); } catch (BadImageFormatException ex) { Debug.WriteLine($"BadImageFormatException loading assembly {assemblyPath}: {ex.Message}"); } catch (FileLoadException ex) { Debug.WriteLine($"FileLoadException loading assembly {assemblyPath}: {ex.Message}"); } catch (Exception ex) { Debug.WriteLine($"Exception loading assembly {assemblyPath}: {ex.Message}"); } if (assembly is not null) { return assembly; } try { assembly = Assembly.LoadFile(assemblyPath); } catch (BadImageFormatException ex) { Debug.WriteLine($"BadImageFormatException loading file {assemblyPath}: {ex.Message}"); } catch (FileLoadException ex) { Debug.WriteLine($"FileLoadException loading file {assemblyPath}: {ex.Message}"); } catch (Exception ex) { Debug.WriteLine($"Exception loading file {assemblyPath}: {ex.Message}"); } return assembly; } #endregion 私有方法 } /// /// 程序集相等性比较器 /// 用于比较两个程序集是否相等,基于程序集名称进行匹配 /// internal class AssemblyEquality : EqualityComparer { /// /// 比较两个程序集是否相等 /// /// 第一个程序集 /// 第二个程序集 /// 如果两个程序集相等则返回 true,否则返回 false public override bool Equals(Assembly? x, Assembly? y) { return (x is null && y is null) || (x is not null && y is not null && AssemblyName.ReferenceMatchesDefinition(x.GetName(), y.GetName())); } /// /// 获取程序集的哈希代码 /// /// 程序集对象 /// 程序集的哈希代码 /// 当程序集为 null 时 public override int GetHashCode(Assembly obj) { ArgumentNullException.ThrowIfNull(obj); return obj.GetName().FullName.GetHashCode(StringComparison.OrdinalIgnoreCase); } } /// /// NuGet 程序包信息记录 /// 表示一个 NuGet 包的基本信息,包括包名和版本 /// public record NuGetPackage { /// /// NuGet 包名称 /// public string PackageName { get; init; } = string.Empty; /// /// NuGet 包版本号 /// public string PackageVersion { get; init; } = string.Empty; /// /// 获取包的完整标识符 /// /// 格式为 "PackageName@PackageVersion" 的字符串 public override string ToString() { return $"{PackageName}@{PackageVersion}"; } }