Search code examples
c#ilrepack

ILRepack'd DLL has IConfiguration, but that doesn't match Microsoft.Extensions.Configuration IConfiguration?


In one .Net standard project, i have required a constructor to pass in IConfiguration from Microsoft.Extensions.Configuration.

This project has then had ILRepack run on it, using the /internalize flag.

I then reference the resulting DLL from another project, which also references Microsoft.Extensions.Configuration, and attempts to pass IConfiguration to the constructor mentioned before.

However, the two types do not match any more, and the following error occurs:

Error CS1503 Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfiguration [C:\Users\me\.nuget\packages\microsoft.extensions.configuration.abstractions\7.0.0\lib\net6.0\Microsoft.Extensions.Configuration.Abstractions.dll]' to 'Microsoft.Extensions.Configuration.IConfiguration [C:\git\ILrepackedProject\src\ILrepackedProject\bin\Debug\netstandard20\ILrepackedProject.dll]'

If i take a look at my ILRepack'd DLL with dotPeek, i see the following: DotPeek showing namespace exists inside repacked dll but with internal interface

Unfortunately, i'm lost as to what i can do here. I need to Repack or internalize the dependencies, otherwise we're going to go into DLL hell with versioning all over again.

I've tried to not internalize them, and it simply states that the Namespace is present in both the MS Official package, and my repacked DLL - with no obvious resolution in sight.

I've tried using AssemblyInfo to make the internals visible to my consuming project with 'InternalsVisibleTo', without success.

I've tried the answer with ILrepack, shown here: C# rename namespaces during build (i.e. the renameinternalized command) with the same results as before.

I've also tried using /internalize:"repackExcludes.txt" with an entry like "^Microsoft.Extensions.Configuration(.){0,}$" which results in the consuming project complaining that the type is defined in two different libraries (my DLL, and Microsofts package) Like so: Image showing that both namespaces described contain the same type

I thought i'd resolved this, and even posted an answer, which is as follows, however the problem persists:


"To fix this problem, i removed all references to Microsoft.Extensions.Configuration.Abstractions from my .net standard and .net 6 projects.

I then noted that there was still somehow a reference to Microsoft.Extensions.Configuration.Abstractions.

This comes from adding the following to my .Net 6 application, to allow it to utilise functionality given to Asp.Net apps:

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

Microsoft.AspNetcore.App happens to include a reference to Microsoft.Extensions.Configuration.Abstractions 6.0.0 While my .Net Standard app was using 7.0.0.

Therefore, they clashed.

To fix this, all projects are now referencing version 6.0.0."


So, current state: Showing different types clashing

Ideas?


Solution

  • To resolve this, I added a delete task to my post-publish tasks in the Csproj, which deletes the DLLs I don't want ILRepacking. In this case, it looks like:

      <Target Name="Custom AfterPublish" AfterTargets="Publish">
        <Delete Files="$(PublishDir)\Microsoft.Extensions.Configuration.dll"></Delete>
        <Delete Files="$(PublishDir)\Microsoft.Extensions.Configuration.Abstractions.dll"></Delete>
      </Target>
    

    Of course, this alone was not enough. I needed to ensure that those DLLs were included somehow, so I added them as dependencies to my project via the nuspec / nupkg.

    I added multi-targetting to the project, and targeted NetStandard2.0,Net6,Net48.

    Finally, I made the code depending on IConfiguration conditional compilation to .Net6. This leaves it out of .Net48 and .NetStandard builds of my package.

    Now, when the package is used in a Net6 project, you get the version with the dependency-added IConfiguration from .Net6, which works fine. With other builds, you don't get the IConfiguration reliant code, and don't end up with the dependency on the two DLL's mentioned above.