在NetStandard2.0项目中使用Roslyn编译动态创建的代码

我正在尝试创建一个可重用的 .NET Standard 2.0 库,该库使用 Roslyn 在运行时将代码动态编译为内存中的程序集。这个动态创建的程序集包含从作为库一部分的基类派生的类。我通过引用该库的应用程序中的反射来实例化它们。项目结构如下所示:


https://img1.sycdn.imooc.com/657e60640001359606500387.jpg

假设我的 netstandard2.0 库中有以下类型:


namespace MyLibrary

{

    public abstract class BaseClass

    {

        public abstract int CalculateSomething();

    }

}

然后,我在 .NET Core 2.2 项目中创建以下单元测试:


namespace NetCore2_2.Tests

{

    public static class RoslynTests

    {

        [Fact]

        public static void CompileDynamicallyAndInvoke()

        {

            // Create syntax tree with simple class

            var syntaxTree = CSharpSyntaxTree.ParseText(@"

using System;

using MyLibrary;


namespace Foo

{

    public sealed class Bar : BaseClass

    {

        public override int CalculateSomething()

        {

            return (int) Math.Sqrt(42);

        }

    }

}");

在此测试中,我首先解析源自 netstandard2.0 库中的BaseClass 的一段 C# 代码。这段代码还引用了System.Math。然后,我创建一个 C# 编译对象,其中包含对(.NET Core 2.2 的)核心库和我的库的引用。该编译对象将 DLL 发送到内存流。如果编译失败,测试将失败并出现包含所有诊断信息的异常。


此单元测试失败并显示以下错误消息:


(7,31):错误CS0012:类型“对象”;在未引用的程序集中定义。您必须添加对程序集“netstandard,Version=2.0.0.0,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”的引用。


(11,26):错误CS0012:类型“对象”;在未引用的程序集中定义。您必须添加对程序集“netstandard,Version=2.0.0.0,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”的引用。

我有以下问题:

  • 这是否不起作用,因为 Roslyn NuGet 包在 .NET Standard 2.0 项目中被引用,因此总是尝试编译为 netstandard2.0 目标框架 Moniker? 我怀疑netstandard2.0 对 System.Object 有不同的定义,转发到目标平台的实际实现。而且我的编译单元中并没有引用这个转发定义。

  • 有办法更改目标框架吗?我查看了CSharpCompilationOptionsEmitOptions,但无法 39;没有找到任何可以让我改变目标框架的东西。

  • 我是否需要使用其他 Roslyn NuGet 软件包,例如 Microsoft.Net.Compilers.Toolset 我尝试避免这种情况,因为实际上想使用默认编译器而不是 NuGet 包中的编译器。


一只名叫tom的猫
浏览 239回答 1
1回答

PIPIONE

它不起作用,因为您的库包含BaseClass,目标为.netstandard2.0(这意味着该库引用了< a i=3>),并且这假设您的库(使用 引用库)应该引用 以正确解析所有相应的类型。因此,您应该添加对它们的引用( 的 或 的类似 )。 (顺便说一句,当您从 库引用 时,您可能应该添加几个额外的库作为 的引用) netstandard.dll 2.0BaseClassnetstandard.dll 2.0netstandard.dll.net47.netstandard.dll.netcore2.2.netstandard2.0.net47path_to_visual_studio\MSBuild\Microsoft\Microsoft.NET.Build.ExtensionsRoslyn Compilation 对目标框架一无所知,而且它不应该对目标框架有任何了解它。 使用树和引用(当然还有一些选项和引用的元数据),因此您应该手动附加编译时所需的引用。 (顺便说一句,如果您有 或 文件,您可以使用 来从在大多数情况下,项目或解决方案文件)CompilationcsprojslnMsBuildWorkspace如果您知道或可以找到编译所需的所有引用,我建议您手动创建Compilation,否则尝试使用Microsoft .CodeAnalysis.Workspaces.MSBuild 用于分析 .csproj 或 .sln 文件,然后从中检索 Compilation他们。 Microsoft.Net.Compilers.Toolset 只是让您可以通过未安装在您的系统上但包含在此包中的编译器来编译您的项目。
打开App,查看更多内容
随时随地看视频慕课网APP