dotnet / project-system

The .NET Project System for Visual Studio
MIT License
967 stars 386 forks source link

Resource designer files generated are incompatible with netstandard #3366

Open livarcocc opened 6 years ago

livarcocc commented 6 years ago

From @emgarten on April 6, 2017 21:49

Resource designer files generated are incompatible with netstandard if a desktop framework is included first in the TargetFrameworks list.

Steps

  1. Create a new netstandard library with VS 2017
  2. Add a resource file to the project
  3. Change $(TargetFramework)=netstandard1.3 to $(TargetFrameworks)=net45;netstandard1.3
  4. Right click on the resource file and select Run Custom Tool
  5. Rebuild

Expected

The project will build

Actual

The project fails to build with an error about being unable to find the Assembly property.

Observation

When a desktop framework is first in the list of target frameworks the designer file is generated incorrectly for netstandard.

.GetTypeInfo() is missing from the designer file:

global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassLibrary12.Resource1", typeof(Resource1).Assembly);

Using netstandard only you would get:

global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassLibrary12.Resource1", typeof(Resource1).GetTypeInfo().Assembly);

Workaround

Using $(TargetFrameworks)=netstandard1.3;net45 instead of $(TargetFrameworks)=net45;netstandard1.3 generates the correct file.

Copied from original issue: dotnet/sdk#1092

livarcocc commented 6 years ago

@srivatsn Is this done by the project system?

livarcocc commented 6 years ago

From @phatcher on January 27, 2018 11:44

@emgarten I have a problem with a library targeting NET 2.0+ and netstandard as depending on which framework is targeted first I get code that is incompatible with the other e.g.

typeof(ExceptionMessage).Assembly

vs

typeof(ExceptionMessage).GetTypeInfo().Assembly

I can't shim this with an extension method as these were only introduced in C# 3.0

I think the designer needs to emit conditional code

livarcocc commented 6 years ago

From @phatcher on January 27, 2018 12:45

Managed to make this work by introducing the extension attribute and a minor shim - posted here for reference...

namespace System.Runtime.CompilerServices
{
#if NET20
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
    internal sealed class ExtensionAttribute : Attribute { }
#endif
}

and

namespace System.Reflection
{
#if NET20 || NET35
    internal static class TypeExtensions
    {
        public static Type GetTypeInfo(this Type type)
        {
            return type;
        }
    }
#endif
}

Won't work for all scenarios but at least allows the resource files to compile

livarcocc commented 6 years ago

@Pilchie is this a project system issue?

livarcocc commented 6 years ago

From @Pilchie on February 12, 2018 21:9

It's a general problem. Most of VS is still completely unaware of the concept of multi-targeting, and the default VS APIs just return the first TFM as the TFM of the project.

In this case, I think the resx designer uses the "Design Time Assembly Resolution" to look at what things resolve in the project.

livarcocc commented 6 years ago

@Pilchie is there a better place to move this issue to?

livarcocc commented 6 years ago

From @Pilchie on March 8, 2018 21:43

project-system is probably the best place.