使用CodeAnalysis CSharpScript(.NET Core)执行用户代码

时间:2017-07-21 05:52:11

标签: c# .net-core roslyn

我正在尝试执行简单用户的公式。

我正在使用MS VS 2017 15.2(26430.16),.NET Core 1.1。

我跟着: https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples

我创建了ASP.NET Core Web App,添加了NuGet包:

Install-Package Microsoft.CodeAnalysis.CSharp.Scripting

但之后该应用程序出错:

An unhandled exception occurred while processing the request.
ArgumentException: Must include private members unless emitting a ref assembly.
Parameter name: IncludePrivateMembers
Microsoft.CodeAnalysis.Compilation.Emit(Stream peStream, Stream pdbStream, Stream xmlDocumentationStream, Stream win32Resources, IEnumerable<ResourceDescription> manifestResources, EmitOptions options, IMethodSymbol debugEntryPoint, Stream sourceLinkStream, IEnumerable<EmbeddedText> embeddedTexts, Stream metadataPEStream, CancellationToken cancellationToken)

我添加

using Microsoft.CodeAnalysis.CSharp.Scripting;

object result = CSharpScript.EvaluateAsync("1 + 2");

但是没有看到,所以我添加了

<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="2.3.1" />

在“MyProject.csproj”中。

但我有同样的错误。

有人能帮助我吗?

更新1:

堆栈:

Microsoft.CodeAnalysis.Compilation.Emit(Stream peStream, Stream pdbStream, Stream xmlDocumentationStream, Stream win32Resources, IEnumerable<ResourceDescription> manifestResources, EmitOptions options, IMethodSymbol debugEntryPoint, Stream sourceLinkStream, IEnumerable<EmbeddedText> embeddedTexts, Stream metadataPEStream, CancellationToken cancellationToken)
Microsoft.AspNetCore.Mvc.Razor.Internal.DefaultRoslynCompilationService.Compile(RelativeFileInfo fileInfo, string compilationContent)
Microsoft.AspNetCore.Mvc.Razor.Internal.RazorCompilationService.Compile(RelativeFileInfo file)
Microsoft.AspNetCore.Mvc.Razor.Internal.CompilerCache.CreateCacheEntry(string relativePath, string normalizedPath, Func<RelativeFileInfo, CompilationResult> compile)
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Razor.Internal.CompilerCache.GetOrAdd(string relativePath, Func<RelativeFileInfo, CompilationResult> compile)
Microsoft.AspNetCore.Mvc.Razor.Internal.DefaultRazorPageFactoryProvider.CreateFactory(string relativePath)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.CreateCacheResult(HashSet<IChangeToken> expirationTokens, string relativePath, bool isMainPage)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.OnCacheMiss(ViewLocationExpanderContext expanderContext, ViewLocationCacheKey cacheKey)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.LocatePageFromViewLocations(ActionContext actionContext, string pageName, bool isMainPage)
Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine.FindView(ActionContext context, string viewName, bool isMainPage)
Microsoft.AspNetCore.Mvc.ViewEngines.CompositeViewEngine.FindView(ActionContext context, string viewName, bool isMainPage)
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor.FindView(ActionContext actionContext, ViewResult viewResult)
Microsoft.AspNetCore.Mvc.ViewResult+<ExecuteResultAsync>d__26.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeResultAsync>d__30.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextResultFilterAsync>d__28.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResultExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeAsync>d__20.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.VisualStudio.Web.BrowserLink.BrowserLinkMiddleware+<ExecuteWithFilter>d__7.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

更新2:

最后我这样做了(没有包):

string user_code = "1 + 2";
string code = $"int? r = {user_code};";
string codeToCompile = @"using System;
namespace RoslynCompile
{
    public class Calculator
    {
        public int? Calculate()
        {
            " + code + @"
            return r;
        }
    }
}";
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(codeToCompile);
string assemblyName = Path.GetRandomFileName();
MetadataReference[] references = new MetadataReference[]
{
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location)
};
CSharpCompilation compilation = CSharpCompilation.Create(
    assemblyName,
    syntaxTrees: new[] { syntaxTree },
    references: references,
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
    EmitResult emitResult = compilation.Emit(ms);
    if (!emitResult.Success)
    {
        // some errors
        IEnumerable<Diagnostic> failures = emitResult.Diagnostics.Where(diagnostic =>
            diagnostic.IsWarningAsError ||
            diagnostic.Severity == DiagnosticSeverity.Error);
    }
    else
    {
        ms.Seek(0, SeekOrigin.Begin);
        Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
        var type = assembly.GetType("RoslynCompile.Calculator");
        var instance = assembly.CreateInstance("RoslynCompile.Calculator");
        var meth = type.GetMember("Calculate").First() as MethodInfo;
        // get result
        int? result = meth.Invoke(instance, null) as int?;
    }
}

1 个答案:

答案 0 :(得分:2)

我不确定导致此错误的原因,但我们回滚到v2.2.0包的Microsoft.CodeAnalysis.CSharp

v2.3.0以来似乎已经开始发生。在撰写本文时,v2.3.1已经出局,但仍会导致此问题。

查看GitHub上的issue