如何将外部别名与nuget一起使用

本文关键字:nuget 一起 别名 外部 | 更新日期: 2023-09-27 18:20:09

我在项目中使用extern alias,因此我需要将引用别名从global更改为其他别名。问题是,如果我使用Nuget添加引用,每次更新包时,别名都会恢复为global。有没有办法阻止这种情况的发生?

如何将外部别名与nuget一起使用

这是nuget引用的已知问题;如果程序集别名根本不受支持(目前):https://github.com/NuGet/Home/issues/4989

幸运的是,存在变通办法;您可以在csproj中添加特殊目标,该目标将动态分配别名:

  <Target Name="ChangeAliasesOfNugetRefs" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
    <ItemGroup>
      <ReferencePath Condition="'%(FileName)' == 'CoreCompat.System.Drawing'">
        <Aliases>CoreCompatSystemDrawing</Aliases>
      </ReferencePath>
    </ItemGroup>
  </Target>

从NuGet 5.7&Visual Studio 2019 Update 7,PackageReference现在支持Aliases属性。没有UI,但您可以直接编辑项目文件:

<ItemGroup>
    <PackageReference Include="NuGet.Versioning" Version="5.8.0" Aliases="ExampleAlias" />
</ItemGroup>

然后在C#代码中:

extern alias ExampleAlias;
namespace PackageReferenceAliasesExample
{
...
        {
            var version = ExampleAlias.NuGet.Versioning.NuGetVersion.Parse("5.0.0");
            Console.WriteLine($"Version : {version}");
        }
...
}

感谢csproj Target更改程序集引用的别名。

我已经用它修复了System.Data_Services.Client/Microsoft.Data.Services.Client冲突,如以下冲突:

错误CS0433:两者中都存在类型"DataServiceContext"'Microsoft.Data.Services.Client,版本=5.8.3.0,区域性=中性,PublicKeyToken=31bf3856ad364e35'和'System.Data.Services.Client,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089'

解决方案是:

  <!--
  Avoid collision of older System.Data.Services.Client with newer Microsoft.Data.Services.Client
  when mixed due to PackageReferences
  -->
  <Target Name="ChangeAliasesOfNugetRefs" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
    <ItemGroup>
      <ReferencePath Condition="'%(FileName)' == 'System.Data.Services.Client'">
        <Aliases>legacy</Aliases>
      </ReferencePath>
    </ItemGroup>
  </Target>

这是不可能的,因为在nuget更新后,它会删除上一个程序集并添加一个新程序集,因此它会删除带有别名的程序集。。。因此,必须将别名再次添加到新更新的程序集中。

您可以在NuGet包中添加一个安装脚本来添加别名。但该包的消费者将无法选择不添加别名。下面是一些可以在脚本中使用的代码。我在powershell方面不是最棒的,所以可能有更好的方法:)

# Standard Install.ps1 parameter list
param($installPath, $toolsPath, $package, $project)
# Name of the alias
$alias = 'MyAlias'
# Load the Microsoft.Build assembly to be able to access MS Build types
Add-Type -AssemblyName Microsoft.Build
# Load the csproj file
$projectObject = New-Object Microsoft.Build.Evaluation.Project($project.FullName)
# Search through the project items to find all references
$referenceItems = $projectObject.Items | where ItemType -eq "Reference" 
# Find the reference that matches the package id 
# (this assumes your assembly name matches your package id)
$item = $referenceItems | select @{Name='Reference'; Expression={$_}},@{Name='AssemblyName'; Expression={(New-Object System.Reflection.AssemblyName($_.UnevaluatedInclude)).Name}} | where AssemblyName -eq $package.Id | select Reference
# If the reference doesnt already have an alias, add one and save the project
if (($item.Reference.Metadata | where Name -eq 'Aliases') -eq $null) {
    $item.Reference.SetMetadataValue('Aliases', $alias)
    $projectObject.Save()
}
# Unload the project when done
$projectObject.ProjectCollection.UnloadAllProjects()