首页 > 解决方案 > 编辑并继续不适用于 Roslyn 编译的类库

问题描述

背景

我正在尝试让 Edit and Continue 使用我在运行时使用 Roslyn 编译的类库。这是为我正在开发的游戏添加修改支持。


问题分解

此源文件已更改。它不再与用于构建正在调试的应用程序的文件版本匹配。


资源

项目 A:DebuggableClassLibrary.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
</Project>

项目 A:Test.cs

using System;

namespace DebuggableClassLibrary
{
    public class Test
    {
        public static int Ct = 0;
        public static void SayHello()
        {
            Ct++;
            Console.WriteLine("Hello World");
        }
    }
}

项目 B:DynamicLoading.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0" />
  </ItemGroup>
</Project>

项目 B:Program.cs

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;

namespace DynamicLoading
{
    class Program
    {
        static void Main(string[] args)
        {
            var references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location),
                MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Console).Assembly.Location)
            };
            var files = Directory.GetFiles(@"C:\Users\mrbri\source\repos\DebuggableClassLibrary\DebuggableClassLibrary", "*.cs");
            var assemblyName = "DebuggableClassLibrary.dll";
            var debug = true;
            var allowUnsafe = false;
            var outputDirectory = @"C:\Users\mrbri\Documents\Test";
            
            var preprocessorSymbols = debug ? new string[] { "DEBUG" } : new string[] { };
            var parseOptions = new CSharpParseOptions(LanguageVersion.Latest, preprocessorSymbols: preprocessorSymbols);
            var compilation = CSharpCompilation.Create(
                assemblyName: assemblyName,
                syntaxTrees: files.Select(f => SyntaxFactory.ParseSyntaxTree(File.ReadAllText(f), parseOptions, f, Encoding.UTF8)), 
                references: references,
                options: new CSharpCompilationOptions(
                    OutputKind.DynamicallyLinkedLibrary,
                    assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default,
                    optimizationLevel: debug ? OptimizationLevel.Debug : OptimizationLevel.Release,
                    allowUnsafe: allowUnsafe
                ));

            var pePath = Path.Combine(outputDirectory, assemblyName);
            var pdbPath = Path.Combine(outputDirectory, Path.ChangeExtension(assemblyName, ".pdb"));

            using (var peStream = new FileStream(pePath, FileMode.Create))
            using (var pdbStream = new FileStream(pdbPath, FileMode.Create))
            {
                var results = compilation.Emit(
                    peStream: peStream, 
                    pdbStream: pdbStream, 
                    options: new EmitOptions(debugInformationFormat: DebugInformationFormat.PortablePdb)
                    );
            }
            
            var assemblyLoadContext = new SimpleUnloadableAssemblyLoadContext();
            var assembly = assemblyLoadContext.LoadFromStream(File.OpenRead(pePath), File.OpenRead(pdbPath));
            var type = assembly.GetTypes().First();
            var method = type.GetMethod("SayHello");

            while (true)
            {
                method.Invoke(null, null);
            }
        }
    }

    internal class SimpleUnloadableAssemblyLoadContext : AssemblyLoadContext
    {
        public SimpleUnloadableAssemblyLoadContext(): base(true) { }
        protected override Assembly Load(AssemblyName assemblyName) => null;
    }
}


尝试解决方案和观察


备择方案

我对确实具有编辑和继续支持的 Roslyn 替代品/包装器持开放态度。

标签: c#.net-coremsbuildroslyn

解决方案


编辑并继续不支持这种情况。正在编辑的库的项目需要在 VS 中加载(在当前解决方案中),并且需要在附加调试器的情况下启动程序。


推荐阅读