在coreclr上使用Roslyn中的System.Dynamic

时间:2016-04-19 12:32:32

标签: c# roslyn coreclr

我对此处提出的问题Using System.Dynamic in Roslyn

有类似的问题

当尝试使用动态对象使用roslyn编译代码时,我收到编译器错误:

CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.SetMember'

我添加了对Microsoft.CSharp的引用。问题只发生在coreclr上运行时,它完全适用于完整的框架。

一个完整的例子是:

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Reflection;
using System.Reflection.Metadata;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

public class Program
{
    public static void Main(string[] args)
    {
        var text = @"using System.Dynamic;

        public class Calculator
        {
            public static object Evaluate()
            {
                dynamic x = new ExpandoObject();
                x.Result = 42;
                return x.Result;
            } 
        }";

        var references = new List<MetadataReference>();

#if DNXCORE50
        // reference system.runtime
        references.Add(GetMetadataReference(typeof(object).GetTypeInfo().Assembly));
        // reference system.dynamic.runtime
        references.Add(GetMetadataReference(typeof(ExpandoObject).GetTypeInfo().Assembly));
        // reference microsoft.csharp
        references.Add(GetMetadataReference(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).GetTypeInfo().Assembly));     
#elif DNX451
        references.Add(MetadataReference.CreateFromFile(typeof(object).Assembly.Location));
        references.Add(MetadataReference.CreateFromFile(typeof(ExpandoObject).Assembly.Location));
        references.Add(MetadataReference.CreateFromFile(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException).Assembly.Location));
#endif

        var tree = SyntaxFactory.ParseSyntaxTree(text);

        var compilation = CSharpCompilation.Create(
            "calc.dll",
            options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
            syntaxTrees: new[] { tree },
            references: references);

        using (var stream = new MemoryStream())
        {
            var compileResult = compilation.Emit(stream);

            if (!compileResult.Success)
            {
                // fails here when running on coreclr
                throw new Exception(compileResult.Diagnostics[0].ToString());
            }
        }
    }

    public static unsafe MetadataReference GetMetadataReference(Assembly assembly)
    {
        byte* b;
        int length;

        MetadataReference reference = null;
        if (assembly.TryGetRawMetadata(out b, out length))
        {
            var moduleMetadata = ModuleMetadata.CreateFromMetadata((IntPtr)b, length);
            var assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
            reference = assemblyMetadata.GetReference();
        }

        return reference;
    }
}

我使用此处描述的技术http://www.strathweb.com/2016/03/roslyn-scripting-on-coreclr-net-cli-and-dnx-and-in-memory-assemblies/来获取对内存程序集的元数据引用,因为Assembly.Location对于coreclr是空的。

project.json文件:

{
  "version": "1.0.0-*",
  "description": "ConsoleApp1 Console Application",
  "authors": [ "steve" ],
  "tags": [ "" ],
  "projectUrl": "",
  "licenseUrl": "",

  "compilationOptions": {
    "emitEntryPoint": true,
    "allowUnsafe": true
  },

  "dependencies": {
    "Microsoft.CodeAnalysis.Common": "1.1.0-rc1-20151109-01",
    "Microsoft.CodeAnalysis.CSharp": "1.1.0-rc1-20151109-01",
    "System.Runtime.Loader": "4.0.0-beta-23516"
  },

  "commands": {
    "ConsoleApp1": "ConsoleApp1"
  },

  "frameworks": {
    "dnx451": {
      "frameworkAssemblies": {
        "System.Runtime": "4.0.10.0",
        "System.Threading.Tasks": "4.0.0.0",
        "System.Text.Encoding": "4.0.0.0",
        "System.IO": "4.0.0.0",
        "System.Reflection": "4.0.0.0"
      }
    },
    "dnxcore50": {
      "dependencies": {
        "Microsoft.CSharp": "4.0.1-beta-23516",
        "System.Collections": "4.0.11-beta-23516",
        "System.Console": "4.0.0-beta-23516",
        "System.Linq": "4.0.1-beta-23516",
        "System.Threading": "4.0.11-beta-23516"
      }
    }
  }
}

我在1.0.0-rc1-update1和update2上试过这个,并尝试添加对其他程序集的引用,但无法弄清楚它失败的原因。

有任何想法吗?

0 个答案:

没有答案