簡體   English   中英

使用Roslyn時,控制台不包含ReadKey的定義

[英]Console does not contain a definition for ReadKey while using Roslyn

我試圖動態編譯代碼並在運行時執行它。 所以我按照http://www.tugberkugurlu.com/archive/compiling-c-sharp-code-into-memory-and-executing-it-with-roslyn作為指導。

示例中給出的代碼完美地起作用。 但是,如果我使用Console.ReadKey()它會給我錯誤CS0117: 'Console' does not contain a definition for 'ReadKey' 我在某處讀到這是因為dotnet核心不支持ReadKey'Console'在asp.net 5控制台應用程序中不包含'ReadKey'的定義 ),但我目前正在使用"Microsoft.NETCore.App"和它Console.ReadKey()如果我在代碼中顯式使用它而不是在使用Roslyn時, Console.ReadKey()可以正常工作。

  • 這是羅斯林的問題還是我做錯了什么?
  • "Microsoft.NETCore.App"dotnet core是一回事嗎? 我懷疑我可能正在使用其他東西作為我的目標(允許我使用ReadKey )和dotnet核心與Roslyn
  • 是否有可能將羅斯林的目標改為其他目標?

提前致謝。

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

namespace DemoCompiler
{
    class Program
    {
        public static void roslynCompile()
        {
            string code = @"
    using System;
    using System.Text;

    namespace RoslynCompileSample
    {
        public class Writer
        {
            public void Write(string message)
            {
                Console.WriteLine(message);
                Console.ReadKey();
            }
        }
    }";
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);

            string assemblyName = Path.GetRandomFileName();
            MetadataReference[] references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)
            };

            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees: new[] { syntaxTree },
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms);

                if (!result.Success)
                {
                    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic => 
                        diagnostic.IsWarningAsError || 
                        diagnostic.Severity == DiagnosticSeverity.Error);

                    foreach (Diagnostic diagnostic in failures)
                        Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                }
                else
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
                    var type= assembly.GetType("RoslynCompileSample.Writer");
                    var instance = assembly.CreateInstance("RoslynCompileSample.Writer");
                    var meth = type.GetMember("Write").First() as MethodInfo;
                    meth.Invoke(instance, new [] {assemblyName});
                }
            }

        }
    }
}

編輯:我試圖引用System.Console.dll但我和System.Private.CoreLib之間發生沖突。 我該如何解決?

一種方法是將<PreserveCompilationContext>true</PreserveCompilationContext> *添加到項目文件中,然后使用Microsoft.Extensions.DependencyModel.DependencyContext獲取當前項目的所有引用程序集:

var references = DependencyContext.Default.CompileLibraries
    .SelectMany(l => l.ResolveReferencePaths())
    .Select(l => MetadataReference.CreateFromFile(l));

這似乎可以避免您獲得的錯誤,但會導致以下警告:

警告CS1701:假設程序集引用'System.Runtime,Version = 4.0.0.0,Culture = neutral,'System.Console'使用的PublicKeyToken = b03f5f7f11d50a3a'匹配標識'System.Runtime,Version = 4.1.0.0,Culture = neutral,PublicKeyToken 'System.Runtime'的= b03f5f7f11d50a3a',您可能需要提供運行時策略

據我所知,這應該不是問題。


*這假設您正在使用csproj / VS2017。 如果您仍在使用project.json / VS2015,則可以使用"buildOptions": { "preserveCompilationContext": true }完成相同的操作"buildOptions": { "preserveCompilationContext": true }

使用該解決方案在https://github.com/dotnet/roslyn/issues/13267上發現了類似的問題。

我已經解決了這個問題(據我所知):

從以下位置復制System.Runtime.dllSystem.Runtime.Extensions.dllC:\\Users\\<user>\\.nuget\\packages\\System.Runtime\\4.1.0\\ref\\netstandard1.5並將它們放在References文件夾中在我的項目中。 那么,而不是引用mscorlib.dllSystem.Private.CoreLib.dll我引用這些

我試過這個並發現僅引用System.Runtime.dll就足夠了(至少在我的情況下)。 為了清楚,我現在使用MetadataReference.CreateFromFile("System.Runtime.dll")而不是MetadataReference.CreateFromFile(typeof(Object).GetTypeInfo().Assembly.Location) ,它引用了工作目錄中的DLL。直。

唯一的缺點是我必須將dll與我的項目一起分發,但考慮到我現在可以在.net核心上正確使用Roslyn而不是將基本框架更改為完整.net,這是可以的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM