9

I've got a solution which contains c# projects, some netstandard 2.0 and others .net4.7. The startup project is of course net47.

At one point, the project creates code using CodeDom and compiles it with CSharpCodeProvider. The problems is that on some machines, it tries to compile the assembly for .netstandard and it fails. The failure is expected: the generated assembly references EF which in only available for full .net framework.

How can I force CSharpCodeProvider to compile against .net47?

public bool GenerateAssembly(
        CodeDomBusinessCode compileUnit
        , string fileName
        , string assembliesPath
        , out IEnumerable<string> errors)
    {
        var provider = new CSharpCodeProvider();
        var parameters = new CompilerParameters
        {
            GenerateExecutable = false,
            OutputAssembly = fileName,
            GenerateInMemory = false
        };
        parameters.ReferencedAssemblies.Add("System.dll");
        parameters.ReferencedAssemblies.Add("System.Runtime.dll");
        parameters.ReferencedAssemblies.Add("System.Core.dll");
        parameters.ReferencedAssemblies.Add("System.ComponentModel.Composition.dll");
        parameters.ReferencedAssemblies.Add(Path.Combine(assembliesPath, "EntityFramework.dll"));
        parameters.ReferencedAssemblies.Add("System.ComponentModel.DataAnnotations.dll");
        parameters.ReferencedAssemblies.Add(Path.Combine(assembliesPath, "GlobalE.Server.Contracts.dll"));

        var results = provider.CompileAssemblyFromDom(parameters, compileUnit.Code);
        if (results.Errors.Count > 0)
        {
            errors = results.Errors.OfType<CompilerError>().Select(x => x.ToString());
            return false;
        }
        errors = null;
        return true;
    }

The error:

error CS0012: The type 'System.IDisposable' is defined in an assembly
 that is not referenced. You must add a reference to assembly 
'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

UPDATE: If I change all projects to net47 (so that there is no netstandard project in the solution), the error will disappear, but I want to keep as many projects on netstandard as possible.

Alireza
  • 5,421
  • 5
  • 34
  • 67
  • @HansPassant Well, EF is definitely present: I can see it in the bin directory, and when I bring the compiled assembly from another computer (only our assembly, not its dependencies) everything starts to work. Apparently, it's only the compilation step. Updated the question to include the actual error message. – Alireza Nov 10 '17 at 10:04
  • Duplicate of https://stackoverflow.com/questions/13253967/how-to-target-net-4-5-with-csharpcodeprovider ? – Simon Mourier Nov 20 '19 at 07:27
  • 2
    CSharpCodeProvider is legacy, it can only target the installed version of .NET, valid options for CompilerVersion is 2.0, 3.0 or 4.0. Your program will be compiled by C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe. That's the legacy C# compiler, last updated in .NET 4.5, it doesn't know anything about .NETStandard. You'll have to [bring your own](https://www.nuget.org/packages/Microsoft.Net.Compilers/). – Hans Passant Nov 24 '19 at 08:49
  • @HansPassant interestingly the answer below solved it for me. You are absolutely correct and I have no idea why adding "netstandard.dll" would work but I can confirm at least in .NET 4.7.2 that is enough to be able to work with packages targeting .NETStandard. – glopes Feb 16 '23 at 12:44

2 Answers2

2

based on your error, you should add "netstandard.dll" as references and it may cause by this note that in .net 4.7 the "System.IDisposable" is in "mscorlib.dll" and in .netstatndard is in "netstandard.dll".

Pbehin
  • 61
  • 5
-2

Try this

var options = new Dictionary<string, string> 
              {
                  { "CompilerVersion", "v4.7" }
              };
var provider = new CSharpCodeProvider(options);
mfkl
  • 1,914
  • 1
  • 11
  • 21