.NET CORE Central Package Management (CPM) 整理
前言
Central Package Management 是netcore 统一包管理工具,在微服务项目中,大量的项目可能会引用不同的dll版本。
比如最常见的Newtonsoft.Json ,有些是11 ,有些是最新12,后续不能进行维护
在微服务项目中,后续的版本升级,大量的项目需要单独修改,有了统一管理工具,只需要维护一个地方即可。
CPM
cpm通过设置Directory.Packages.props 文件来进行控制,Directory.Packages.props文件内容为xml文件格式,通过设置
ManagePackageVersionsCentrally为true进行开启
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> </PropertyGroup> <ItemGroup> <PackageVersion Include="Newtonsoft.Json" Version="13.0.1" /> </ItemGroup> </Project>
cpm的功能可以嵌套:
Repository
|-- Directory.Packages.props
|-- Solution1
|-- Directory.Packages.props
|-- Project1
|-- Solution2
|-- Project2
比如 Project1 会找Solution1 下面的Directory.Packages.props 文件,但cpm不会自动导入更加上层Directory.Packages.props文件,这里需要自己手动导入,
<Project> <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" /> <ItemGroup> <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" /> </ItemGroup> </Project>
引入CPM后,现有项目的包管理中就不能有 Version 属性
<ItemGroup> <PackageReference Include="Newtonsoft.Json" /> </ItemGroup>
迁移到CPM
CPM有了之后,现有的项目需要重新整理一下,需要从不同的项目提取所有的包和其版本,然后删除 原有项目Version属性,最好统一整理到 Directory.Packages.props中去。
这里就写一个代码进行迁移
public static void HandlePackRefrence(string csprojDir, SortedDictionary<string,string> packDict) { Log.Information("start handle {0}", csprojDir); XElement root=XElement.Load(csprojDir); //find package element var packItemGroupEle = root.Elements("ItemGroup").Where(e => e.Elements("PackageReference").Count() > 0).FirstOrDefault(); if(packItemGroupEle == null) { return; } foreach (var item in packItemGroupEle.Elements("PackageReference")) { string name = (string)item.Attribute("Include"); string version= (string)item.Attribute("Version"); Log.Information($"{name} - {version}"); if(string.IsNullOrEmpty(name) || string.IsNullOrEmpty(version)) { continue; } //remove version item.Attribute("Version").Remove(); //save all package info packDict[name] = version; } root.Save(csprojDir); Log.Information("end handle {0}", csprojDir); }
以上方法先找到对应的工程文件 ,找到对应的包,先移除Version 属性,再保留到 SortedDictionary 字典(这里便于自动排序,美观)
有了所有的包信息,直接写入Directory.Packages.props 文件
XElement packProps = new XElement("Project", new XElement("PropertyGroup", new XElement("ManagePackageVersionsCentrally", true)), new XElement("ItemGroup", from kv in config select new XElement("PackageVersion", new XAttribute("Include", kv.Key), new XAttribute("Version", kv.Value)))) ;
总结
这样所有的包都统一在 Directory.Packages.props 文件中,便于后续维护和修改!