You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#:过滤调用程序集的引用,排除包引用以查找特定类型

解决方案:过滤项目引用并查找特定类型

核心思路

要区分项目引用和NuGet包引用且不依赖程序集Name属性,可通过以下特征判定:

  • 包引用的程序集通常携带PackageId这类NuGet专属元数据
  • 项目引用的程序集输出路径一般与主程序集(调用程序集)处于同一目录或解决方案关联目录
  • 包引用的程序集大多来自系统级NuGet缓存目录

具体实现代码

using System;
using System.Linq;
using System.Reflection;

public class AssemblyLocator
{
    public static Type FindTargetTypeInProjectReferences(string targetTypeFullName)
    {
        // 获取调用方的程序集(即解决方案内的可执行程序集)
        Assembly callingAssembly = Assembly.GetCallingAssembly();
        string mainAssemblyDir = System.IO.Path.GetDirectoryName(callingAssembly.Location);

        // 过滤引用,剔除所有包引用
        var projectAssemblies = callingAssembly.GetReferencedAssemblies()
            .Select(asmName => 
            {
                try
                {
                    return Assembly.Load(asmName);
                }
                catch
                {
                    // 加载失败的直接排除(多为未复制到输出目录的包引用)
                    return null;
                }
            })
            .Where(asm => asm != null)
            .Where(asm => 
            {
                // 检查是否包含NuGet包元数据,有则判定为包引用
                bool isPackageRef = asm.GetCustomAttributes<AssemblyMetadataAttribute>()
                    .Any(attr => attr.Key == "PackageId");
                
                // 检查是否来自NuGet缓存目录
                bool isFromNuGetCache = asm.Location.Contains(@".nuget\packages\") 
                    || asm.Location.Contains(@"/.nuget/packages/");
                
                // 检查是否和主程序集同目录(项目引用默认输出到此)
                bool isInMainOutputDir = System.IO.Path.GetDirectoryName(asm.Location) == mainAssemblyDir;

                // 保留规则:非包引用+非缓存目录,或者位于主输出目录的程序集
                return !isPackageRef && !isFromNuGetCache || isInMainOutputDir;
            });

        // 在筛选后的项目引用中查找目标类型
        foreach (var asm in projectAssemblies)
        {
            try
            {
                Type foundType = asm.GetType(targetTypeFullName);
                if (foundType != null)
                {
                    return foundType;
                }
            }
            catch
            {
                // 跳过加载类型失败的异常情况
                continue;
            }
        }

        return null;
    }
}

关键逻辑说明

  • 加载引用程序集:通过Assembly.Load加载引用项,加载失败的直接排除(包引用常未被复制到输出目录)
  • 目录匹配:项目引用的程序集默认会同步输出到主程序集目录,以此作为核心判断依据
  • 元数据识别:利用NuGet包自动注入的AssemblyMetadataAttribute标记,直接识别包引用
  • 缓存目录排查:通过路径特征直接排除来自NuGet全局缓存的程序集

注意事项

  • 若项目引用的程序集配置了自定义输出目录,需调整mainAssemblyDir相关的判断逻辑,匹配自定义路径
  • 对于强签名的程序集,也可通过公钥令牌区分,但需预先知晓项目引用的公钥信息,灵活性稍逊

内容的提问来源于stack exchange,提问作者Sarwan Surchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:04:53