Elie Steinbock
Elie Steinbock

Reputation: 5088

How to use extern alias with nuget

I use extern alias in my project so I need to change the reference alias from global to something else. The problem is that if I use Nuget to add the reference, every time I update the package the alias reverts to global. Is there a way to stop this from happening?

Upvotes: 28

Views: 18061

Answers (5)

Borislav Ivanov
Borislav Ivanov

Reputation: 5360

Starting with NuGet 5.7 & Visual Studio 2019 Update 7, PackageReference now supports the Aliases property. There is no UI, but you can edit directly the project file:

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

And then in the C# code:

extern alias ExampleAlias;

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

Upvotes: 21

Marek Ištv&#225;nek
Marek Ištv&#225;nek

Reputation: 51

Thank You for the csproj Target to change aliases of assembly references.

I have used it to fix System.Data.Services.Client/Microsoft.Data.Services.Client collision like this one:

error CS0433: The type 'DataServiceContext' exists in both 'Microsoft.Data.Services.Client, Version=5.8.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' and 'System.Data.Services.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'

The solution is:

  <!--
  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>

Upvotes: 5

Vitaliy Fedorchenko
Vitaliy Fedorchenko

Reputation: 9235

This is know issue with nuget references; in case of assembly alias is not supported at all (yet): https://github.com/NuGet/Home/issues/4989

Fortunately workaround exists; you can add special target to your csproj that will assign aliases on-the-fly:

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

Upvotes: 36

TylerOhlsen
TylerOhlsen

Reputation: 5578

You could add an install script to your NuGet package to add the alias. But the consumer of the package would not be able to opt-out of adding the alias. Here's some code you could use in the script. I'm not the greatest at powershell so there may be a better way to do it :)

# 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()

Upvotes: 0

Sherif Ahmed
Sherif Ahmed

Reputation: 1946

it's not possible because after nuget update it removes the previous assembly and add a new assembly so it removes the assembly with it's alias ... so you must add again your alias to the new updated assembly.

Upvotes: 0

Related Questions