在Roslyn中使用System.Dynamic

98

我修改了昨天发布的新版本Roslyn附带的示例,使用了dynamic和ExpandoObject,但是我遇到了一个编译错误,不知道该如何解决。错误信息如下:

(7,21):错误 CS0656:缺少编译器所需的成员 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

在新编译器中不能使用动态类型吗?我该如何解决这个问题?这是我更新后的示例:

[TestMethod]
public void EndToEndCompileAndRun()
{
    var text = @"using System.Dynamic;
    public class Calculator
    {
        public static object Evaluate()
        {
            dynamic x = new ExpandoObject();
            x.Result = 42;
            return x.Result;
        } 
    }";

    var tree = SyntaxFactory.ParseSyntaxTree(text);
    var compilation = CSharpCompilation.Create(
        "calc.dll",
        options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
        syntaxTrees: new[] {tree},
        references: new[] {new MetadataFileReference(typeof (object).Assembly.Location), new MetadataFileReference(typeof (ExpandoObject).Assembly.Location)});

    Assembly compiledAssembly;
    using (var stream = new MemoryStream())
    {
        var compileResult = compilation.Emit(stream);
        compiledAssembly = Assembly.Load(stream.GetBuffer());
    }

    Type calculator = compiledAssembly.GetType("Calculator");
    MethodInfo evaluate = calculator.GetMethod("Evaluate");
    string answer = evaluate.Invoke(null, null).ToString();

    Assert.AreEqual("42", answer);
}
5个回答

221

我认为你需要引用 Microsoft.CSharp.dll 程序集


3
自从引入了“dynamic”以来,这已经成为必需的内容。 - khellang
19
如果微软能够提供一个错误提示信息,告诉你这个问题的原因,那么这将会使事情变得更加容易。 - kjbartel
1
我不知道这是否解决了问题,但我在我的Views/Web.config <namespaces>节点中添加了<add namespace="Microsoft.CSharp" />。现在编译器错误已经消失了。 - Don Rolling
3
就你需要的翻译内容而言,意思是:如果要添加 Microsoft.CSharp.dll,就意味着 var scriptOptions = ScriptOptions.Default.WithReferences("Microsoft.CSharp"),也就是不需要使用 dll 文件。这让我困惑了几分钟 :) - Jon H
我尝试在.NET Core 2.1应用程序控制台中运行Rush代码。 我已经在项目中添加了Microsoft.CSharp.dll引用,并且在代码中也使用了MetadataFileReference,但我始终收到相同的错误信息。 - Renzo Ciot
显示剩余2条评论

11

为了让代码在 .Net Core 2.1 中运行,我不得不在编译中添加以下引用:

var compilation = CSharpCompilation.Create(
    "calc.dll",
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary),
    syntaxTrees: new[] {tree},
    references: new[] {
        MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
        MetadataReference.CreateFromFile(typeof(ExpandoObject).Assembly.Location),
        MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.CSharp")).Location),
        MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("netstandard")).Location),
        MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("mscorlib")).Location),
        MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("System.Runtime")).Location),            
    }
);

你可以将System.Linq.Expressions、System.Private.CoreLib、System.Runtime和Microsoft.CSharp作为字符串获取。 - Simon Mourier
1
为了让我的代码在 .net 3.1 中工作,关键点是 MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("netstandard")).Location) - Feri

7

ASP.NET MVC专用:

如果您在MVC 6控制器中忘记在POST方法中加入[FromBody],则会出现此错误。

    [HttpPost("[action]")]
    public void RunReport([FromBody]dynamic report)
    {
        ...
    }

.NET Core默认项目已经包括了Microsoft.CSharp引用,但你几乎会得到相同的消息。当添加了[FromBody]后,你现在可以发布JSON并动态访问属性 :-)

明白这并不适用于2014年发布的原始问题(尽管希望承认它是有帮助的)。不确定在这种情况下SO礼仪规定了什么。 - t.j.
公正的观点 :) 我只是把它添加在这里,因为它似乎很难理解,而这个错误恰好可以匹配。 - Simon_Weaver

4
你可能还想检查所有项目引用的属性。确保任何引用都使用比2.0更新的.NET。我有一个项目引用了同一解决方案中的另一个项目,必须使用更新的.NET框架目标重新构建依赖项。
请参阅此帖子
另外,不要忘记像@Alberto所说的那样将Microsoft.CSharp引用添加到你的主项目中。

3
如果您的项目针对的是 .Net Core 或 .Net Standard,那么您可以安装 Microsoft.CSharp NuGet 包来解决这个错误,而不是添加引用。

Microsoft CSharp必须被您的Roslyn编译器引用。它是可用的,或者可以作为普通引用添加到您的调用方项目中。请记住,在Roslyn使用中,将Copy Local设置为true在引用的属性中,否则您生成的代码无法找到它。然后将MetadataReference.CreateFromFile(Assembly.Load(new AssemblyName("Microsoft.CSharp")).Location)添加到references[]中以将其添加到您的编译器中。 - Goodies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接