以前曾經使用過Nuget V2 (NuGet.Core)來操作 nuget,因為需要所以改用 V3,這裡就紀錄使用方式
開發環境
VS 2017
NuGet.PackageManagement 4.9.3
安裝套件
Install-Package NuGet.PackageManagement
下載
Settings.LoadDefaultSettings(null):指定nuget.config的位置,不指定則使用預設(nuget.exe.config)
SettingsUtility.GetGlobalPackagesFolder(settings):預設快取位置,C:\Users\yao\.nuget\packages\
NullLogger.Instance:ILogger 實作,我不打算實作Log,所以使用內建的NullLogger
SourceCacheContext:快取
PackageDownloadContext:下載位置
SourceRepositoryProvider:倉儲位置為 nuget.config 的 packagesources 節點,https://docs.microsoft.com/zh-tw/nuget/reference/nuget-config-file#packagesources
PackageDownloader.GetDownloadResourceResultAsync:回傳 Stream,把它複製 FileStream 即可;因為有多個倉儲,只要下載到檔案,就離開迴圈
public static async Task DownloadAsync(string packageId, string version) { var package = new PackageIdentity(packageId, NuGetVersion.Parse(version)); var settings = Settings.LoadDefaultSettings(null); var globalFolder = SettingsUtility.GetGlobalPackagesFolder(settings); var logger = NullLogger.Instance; var cancelToken = CancellationToken.None; var sourceRepositoryProvider = new SourceRepositoryProvider(settings, Repository.Provider.GetCoreV3()); var downloadFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Download"); using (var cacheContext = new SourceCacheContext()) { var downloadContext = new PackageDownloadContext(cacheContext, downloadFolder, true); var repositories = sourceRepositoryProvider.GetRepositories(); foreach (var repository in repositories) { var downloadResult = await PackageDownloader.GetDownloadResourceResultAsync(repository, package, downloadContext, globalFolder, logger, cancelToken); if (downloadResult != null) { var downloadFile = $@"{downloadFolder}\{package.Id}.{package.Version}.nupkg"; using (var fileStream = File.Create(downloadFile)) { downloadResult.PackageStream.Seek(0, SeekOrigin.Begin); await downloadResult.PackageStream.CopyToAsync(fileStream); } break; } } } }
取得所有依賴組件
public static async Task<ISet<PackageIdentity>> GetAllDependenciesAsync(string packageId, string version) { var package = new PackageIdentity(packageId, NuGetVersion.Parse(version)); var settings = Settings.LoadDefaultSettings(null); var nuGetFramework = NuGetFramework.AnyFramework; var logger = NullLogger.Instance; var cancelToken = CancellationToken.None; var sourceRepositoryProvider = new SourceRepositoryProvider(settings, Repository.Provider.GetCoreV3()); var availablePackages = new HashSet<PackageIdentity>(PackageIdentityComparer.Default); using (var cacheContext = new SourceCacheContext()) { var repositories = sourceRepositoryProvider.GetRepositories(); await GetDependenciesAsync(package, nuGetFramework, cacheContext, logger, repositories, availablePackages, cancelToken); } return availablePackages; }
這是依各遞迴方法,主要是dependencyInfoResource.ResolvePackage 這個方法取得依賴組件,dependencyInfo.Dependencies 則是存放結果。
private static async Task GetDependenciesAsync(PackageIdentity package, NuGetFramework framework, SourceCacheContext cacheContext, ILogger logger, IEnumerable<SourceRepository> repositories, ISet<PackageIdentity> availablePackages, CancellationToken cancellation) { if (availablePackages.Contains(package)) { return; } foreach (var sourceRepository in repositories) { var dependencyInfoResource = await sourceRepository.GetResourceAsync<DependencyInfoResource>(); var dependencyInfo = await dependencyInfoResource.ResolvePackage(package, framework, cacheContext, logger, cancellation); if (dependencyInfo != null) { if (!availablePackages.Contains(dependencyInfo)) { availablePackages.Add(dependencyInfo); foreach (var dependency in dependencyInfo.Dependencies) { var dependPackage = new PackageIdentity(dependency.Id, dependency.VersionRange.MinVersion); await GetDependenciesAsync(dependPackage, framework, cacheContext, logger, repositories, availablePackages, cancellation); } } break; } } }
搜尋組件
大部分的用法都跟上述一樣,差在這裡是透過 SearchAsync 方法來取得相關組件
var searchResource = await sourceRepository.GetResourceAsync<PackageSearchResource>();
var metadatas = await searchResource.SearchAsync(null, new SearchFilter(false), skip, take, logger, cancelToken);
完整範例在 GetAllPackagesAsync 方法,是呼叫另一各遞迴方法每次搜尋 10 筆組件
參考
https://martinbjorkstrom.com/posts/2018-09-19-revisiting-nuget-client-libraries
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET