天道酬勤

.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 文件中,便于后续维护和修改!

posted @ 2024-12-09 11:28  JulyLuo  阅读(15)  评论(0编辑  收藏  举报