Не удается скомпилировать простой динамический код после миграции на .netstandard 2.0 (CodeDom выдает System.PlatformNotSupportedException)

Попытка скомпилировать этот образец кода:

var c = new CSharpCodeProvider();
var cp = new CompilerParameters();
var className = $"CodeEvaler_{Guid.NewGuid().ToString("N")}";
// doesn't work with or without netstandard reference
var netstandard = Assembly.Load("netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51");
cp.ReferencedAssemblies.Add(netstandard.Location);
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;

var sb = new StringBuilder("");

sb.Append("namespace Jobs.Dynamic{ \n");
sb.Append($"public class {className} {{\n");
sb.Append($"public object RunSnippetCode()\n{{\n");
sb.Append("\nreturn null;\n");
sb.Append("\n}\n");
sb.Append("}");
sb.Append("}");

CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());

До перехода на .netstandard 2.0 все было ок

Должен быть сгенерирован простой класс, и он работает, если просто скопировать код и запустить его в Visual Studio. Класс с одним методом, возвращающим null. Теперь метод CompileAssemblyFromSource выдает

System.PlatformNotSupportedException: операция не поддерживается на этой платформе. в Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(параметры CompilerParameters, имена файлов String[]) в Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(параметры CompilerParameters, источники String[]) в CnetContent.Jobs.DynamicCode.. ctor (использования IEnumerable1 referencedAssemblies, IEnumerable1, String methodArgs, String codeSnippet) в CnetContent.Jobs.Core.JobBase.EvalRunCondition (строка и ошибка)

Я обновил System.CodeDom, и эта библиотека поддерживает .netstandard 2.0, но этот код по-прежнему не работает. Не удалось найти ни одного случая с похожими проблемами. Любые идеи? Заранее спасибо!


person Andrei Barbolin    schedule 04.04.2018    source источник
comment
Если что-то поддерживается .NET Standard, это просто означает, что классы доступны. Они не обязательно имеют полную реализацию на всех платформах (или даже на любых платформах, если вам не повезло). Вы запускаете это в Windows?   -  person Jeroen Mostert    schedule 04.04.2018
comment
@jeroen-mostert, полностью понимаю, что реализация может быть неполной, но я не делаю ничего особенного, просто пытаюсь скомпилировать почти пустой класс ... Да, я запускаю это в Windows.   -  person Andrei Barbolin    schedule 04.04.2018
comment
О, есть еще это. Это может автоматически сдвинуть Roslyn в API CodeDOM, или вы можете подумать о переходе на полный Roslyn и вообще не проходить через CodeDOM. Дело не в том, что он особенный, а в том, что кто-то написал необходимые привязки к сборкам для конкретной платформы - CSharpCodeGenerator используется для жутких вещей, таких как использование локально установленного компилятора C#, что-то, что не особенно переносимо (или надежно).   -  person Jeroen Mostert    schedule 04.04.2018
comment
Я уже думал об изменении CodeDom на Roslyn. Просто последняя надежда, что у кого-то есть очень простое решение этой проблемы.   -  person Andrei Barbolin    schedule 04.04.2018
comment
@AndreiBarbolin: есть решение твоей проблемы? Я столкнулся с той же проблемой :(   -  person Amir    schedule 08.05.2018
comment
@Amir, я заменил CodeDom на Roslyn. Roslyn дает дополнительную информацию об ошибках компиляции.   -  person Andrei Barbolin    schedule 09.05.2018
comment
@AndreiBarbolin: моя проблема решена с помощью проекта приложения Windows вместо консольного проекта. кстати спасибо за ответ.   -  person Amir    schedule 09.05.2018
comment
По этой ссылке. Эти API больше не поддерживаются в ядре и .Net 5+, вот ссылка: docs.microsoft.com/en-us/dotnet/core/compatibility/   -  person Reza    schedule 17.04.2021


Ответы (2)


У меня была такая же проблема с .NetCore 2, но с большим проектом CodeDOM. Мое решение, которое я сейчас создаю, заключается в создании исходного кода из CodeDom и последующей передаче его в Roslyn. (Поскольку Roslyn был упомянут в комментарии, но было опубликовано только решение .NET Framwork)

Вот хороший пример использования Roslyn — просто добавьте

Microsoft.CodeAnalysis.CSharp Пакет NuGet и System.Runtime.Loader Пакет NuGet

а затем используйте код здесь (или просто следуйте примеру): https://github.com/joelmartinez/dotnet-core-roslyn-sample/blob/master/Program.cs

person Michael P    schedule 02.07.2018
comment
Это решение сработало для меня, единственная проблема в том, что мне пришлось удалить пакет CodeDOM из проекта cs и другие неиспользуемые пакеты, чтобы он заработал. - person Alejandro Cortes; 04.12.2018
comment
Будет ли CodeDom когда-нибудь поддерживаться .Net Core? - person Felipe Oriani; 29.05.2019

В моем случае я переносил проект с .NET Framework 4.7.2 на .NET Standard 2.0. В этом проекте у меня есть код для создания сборки во время выполнения с использованием CSharpCodeProvider. Мог скомпилировать проект, но затем во время выполнения мой код выдал исключение при создании сборки из Dom. Я получил эту ошибку:

CS0012: The type 'System.Object' 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'.

Как следствие, сборка не была создана во время выполнения.

Чтобы исправить это, я добавил .netstandard для компилятора в качестве ссылочной сборки, например:

var compilerParameters = new CompilerParameters();
var netstandard = Assembly.Load("netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51");
compilerParameters.ReferencedAssemblies.Add(netstandard.Location);

Это помогло мне.

person Thomas Purrer    schedule 05.02.2021
comment
Должен был работать с CompilerVersion, v4.7.2, введенным в ctor CSharpCodeProvider, но это не так. Вместо этого работает ваш ответ, спасибо !!! - person Patrick from NDepend team; 19.05.2021
comment
Я не заметил, что мой проект был ядром .NET, и мне пришлось переключиться на полную структуру. Тогда это сработало. - person micahhoover; 07.06.2021