Search code examples
c#.net-6.0.net-standard-2.0multitargeting

CS0234 "The Type or namespace name" error with multi-target project with #if


I'm making a private nuget-package library with support for dependency injection. If the project using this nuget-package is running .net6 or later, I wish for it to be a .Net6.0 library and to use Microsoft dependency injection. Otherwise I wish for it to be a netstandard2.0 and to use StructureMap.

My .csproj file looks like this (cleaned up unnecessary lines):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
    <PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
  </ItemGroup>

  <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
    <PackageReference Include="StructureMap" Version="4.7.1" />
  </ItemGroup>
</Project>

And my extension method to use either Microsoft.Extensions.DependencyInjection or StructureMap looks like this (also removed unnecessary lines here):

using System;
using CustomApiClient.ApiClient;
#if NET6_0_OR_GREATER
using Microsoft.Extensions.DependencyInjection;
#else
using StructureMap;
#endif

namespace CustomApiClient.Extensions
{
    public static class DependencyInjectionExtensions
    {
#if NET6_0_OR_GREATER
        public static IServiceCollection RegisterApiClient(this IServiceCollection services)
        {
            if (services == null)
            {
                throw new ArgumentNullException(nameof(services));
            }

            services.AddSingleton<IApiHelper, ApiHelper>()
                .AddScoped<IClient, Client>();

            return services;
        }
#else
        public static IContainer StructureMapRegisterApiClient(this IContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            container.Configure(x =>
            {
                x.For<IApiHelper>().Use<ApiHelper>().Singleton();
                x.For<IClient>().Use<Client>();
            });

            return container;
        }
#endif
    }
}

First of all Visual Studio displays the entire #if NET6_0_OR_GREATER part of the extension-method class as greyed out. As well as in the using section in the top. Everything between #else and #endif looks like normal code, with colors and such.

and then I have three errors:

Error   CS0234  The type or namespace name 'Extensions' does not exist in the namespace 'Microsoft' (are you missing an assembly reference?)    ApiClient (net6.0)  PATH\DependencyInjectionExtensions.cs   4   Active

Error   CS0246  The type or namespace name 'IServiceCollection' could not be found (are you missing a using directive or an assembly reference?)    SkolenhetsregistretApiClient (net6.0)   PATH\ApiClient\Extensions\DependencyInjectionExtensions.cs  14  Active

If don't do the #if statements in the dependency injection code and I keep all packagereferences in a without conditions, it builds just fine.

I tried swapping the frameworks in but that didn't change anything. It is as if it ignores the net6.0 Framework completely.


Solution

  • Answering myself. Devil is in the details. For reasons unknown my package reference was set to update as this:

    <PackageReference Update="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
    

    Instead of Include as this:

    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />