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

如何配置NuGet Client SDK指定特定目标框架?

问题描述

我有一段代码可实现将NuGet包及其依赖项下载至指定文件夹,但这段代码会下载所有受支持的.NET版本(如.NET Standard 2.1、UWP、net45等)的二进制文件。请问如何配置它,使其仅下载适用于特定目标框架(例如.NET 6.0)的包版本?

补充说明:额外请教如何在运行时动态加载目标包所需的程序集,若需修改NuGet以包含json.deps也可接受。

现有代码示例

public async Task<HashSet<PackageIdentity>> InstallPackageAndDependenciesAsync(PackageIdentity identity)
{
    bool allowUnlisted = false;
    bool includePrelease = true;

    try
    {
        ResolutionContext resolutionContext = new ResolutionContext(
            DependencyBehavior.Lowest,
            includePrelease,
            allowUnlisted,
            VersionConstraints.ExactMajor | VersionConstraints.ExactMinor);

        INuGetProjectContext projectContext = new BlankProjectContext(Settings.Settings, new NuGetCustomLogger());

        var installActions = await LocalNuGetPackageManager.PreviewInstallPackageAsync(
            LocalNuGetPackageManager.PackagesFolderNuGetProject, identity,
            resolutionContext, projectContext,
            new[] { RemoteNuGetFeed }, Array.Empty<SourceRepository>(),
            CancellationToken.None);

        var sourceCache = new SourceCacheContext();
        await LocalNuGetPackageManager.ExecuteNuGetProjectActionsAsync(LocalNuGetPackageManager.PackagesFolderNuGetProject, installActions, projectContext, sourceCache, CancellationToken.None);

        return new HashSet<PackageIdentity>(installActions.Select(action => action.PackageIdentity));
    }
    catch (Exception ex)
    {
        throw;
    }
} 
解决方案

一、仅下载指定目标框架的NuGet包

要实现只下载对应.NET 6.0的包,核心是让NuGet在解析依赖时只筛选兼容指定框架的包版本,具体修改如下:

  1. 定义目标框架
    先明确要适配的目标框架:

    var targetFramework = FrameworkName.Parse("net6.0");
    var targetFrameworks = new[] { targetFramework };
    
  2. 自定义NuGet项目类
    默认的PackagesFolderNuGetProject未指定目标框架,需要创建自定义类来暴露目标框架信息:

    public class TargetedPackagesFolderNuGetProject : PackagesFolderNuGetProject
    {
        private readonly IEnumerable<FrameworkName> _targetFrameworks;
    
        public TargetedPackagesFolderNuGetProject(string packagesPath, IEnumerable<FrameworkName> targetFrameworks)
            : base(packagesPath)
        {
            _targetFrameworks = targetFrameworks;
        }
    
        public override IEnumerable<FrameworkName> GetTargetFrameworks()
        {
            return _targetFrameworks;
        }
    }
    
  3. 修改原代码逻辑
    替换原有项目实例,并给ResolutionContext绑定目标框架,确保依赖解析时只匹配指定框架:

    // 替换默认的项目实例
    var targetedProject = new TargetedPackagesFolderNuGetProject(LocalNuGetPackageManager.PackagesFolder, targetFrameworks);
    
    // 初始化带目标框架的解析上下文
    var resolutionContext = new ResolutionContext(
        DependencyBehavior.Lowest,
        includePrelease,
        allowUnlisted,
        VersionConstraints.ExactMajor | VersionConstraints.ExactMinor)
    {
        TargetFrameworks = targetFrameworks
    };
    

    后续在PreviewInstallPackageAsync和ExecuteNuGetProjectActionsAsync方法中,用targetedProject替代原来的PackagesFolderNuGetProject即可。

    调整后,NuGet会只下载与.NET 6.0兼容的包二进制文件,不再包含其他无关框架的内容。

二、运行时动态加载程序集

结合deps.json和AssemblyLoadContext可以实现依赖的正确加载,步骤如下:

  1. 确保保留deps.json文件
    NuGet默认会下载包的完整内容,其中包含deps.json,只需确保解压包时不排除该文件即可。

  2. 自定义AssemblyLoadContext
    基于deps.json的依赖信息来加载程序集:

    public class NuGetAssemblyLoadContext : AssemblyLoadContext
    {
        private readonly DependencyContext _dependencyContext;
        private readonly string _packagesFolder;
    
        public NuGetAssemblyLoadContext(string depsJsonPath, string packagesFolder)
            : base(isCollectible: true)
        {
            _packagesFolder = packagesFolder;
            using var stream = File.OpenRead(depsJsonPath);
            _dependencyContext = DependencyContext.Load(stream);
        }
    
        protected override Assembly? Load(AssemblyName assemblyName)
        {
            // 从依赖上下文查找程序集路径
            var library = _dependencyContext.RuntimeLibraries
                .FirstOrDefault(l => l.Name.Equals(assemblyName.Name, StringComparison.OrdinalIgnoreCase));
    
            if (library != null)
            {
                var assemblyPath = Path.Combine(_packagesFolder, $"{library.Name}/{library.Version}", 
                    library.RuntimeAssemblyGroups.First().Assemblies.First().Path);
    
                if (File.Exists(assemblyPath))
                {
                    return LoadFromAssemblyPath(assemblyPath);
                }
            }
    
            // 回退到默认加载逻辑
            return Default.LoadFromAssemblyName(assemblyName);
        }
    }
    
  3. 加载示例
    找到目标包的deps.json路径,初始化加载上下文后即可加载程序集:

    // 示例:加载Newtonsoft.Json的程序集
    var depsPath = Path.Combine("./packages/Newtonsoft.Json/13.0.3", "Newtonsoft.Json.deps.json");
    var loadContext = new NuGetAssemblyLoadContext(depsPath, "./packages");
    var assembly = loadContext.LoadFromAssemblyName(new AssemblyName("Newtonsoft.Json"));
    
    // 动态调用示例
    var jsonConvertType = assembly.GetType("Newtonsoft.Json.JsonConvert");
    var serializeMethod = jsonConvertType.GetMethod("SerializeObject", new[] { typeof(object) });
    var result = serializeMethod.Invoke(null, new object[] { new { Name = "Test" } });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:15:07