Roslyn c#csharp编译-编译动态

Roslyn c#csharp编译-编译动态,c#,.net,dynamic,roslyn,C#,.net,Dynamic,Roslyn,Roslyn编译器和动力学-->我正在尝试编译仅在运行时已知的属性。 在VisualStudio中编译时,代码可以正常工作。使用Roslyn编译时,动态属性为“未知” 在这个单元测试示例中,我有一个从DynamicObject继承的MyObject。属性随一个简单的键值字典提供 当以硬编码方式使用“MyObject”时,我可以调用属性Hello。我实际上可以在编译时使用任何属性。。不存在的属性在运行时将出错。(预期行为) 在传递给roslyn编译器的代码中使用“MyObject”时,我不能在动态

Roslyn编译器和动力学-->我正在尝试编译仅在运行时已知的属性。
在VisualStudio中编译时,代码可以正常工作。使用Roslyn编译时,动态属性为“未知”

在这个单元测试示例中,我有一个从DynamicObject继承的MyObject。属性随一个简单的键值字典提供

当以硬编码方式使用“MyObject”时,我可以调用属性Hello。我实际上可以在编译时使用任何属性。。不存在的属性在运行时将出错。(预期行为)

在传递给roslyn编译器的代码中使用“MyObject”时,我不能在动态对象上使用任何属性。在这里,属性“Hello”给了我一个错误:

CS1061 - 'MyObject' does not contain a definition for 'Hello' and no accessible extension method 'Hello' accepting a first argument of type 'MyObject' could be found (are you missing a using directive or an assembly reference?)
我错过了什么

单元测试示例:

使用系统;
使用System.Collections.Generic;
使用System.Diagnostics.Contracts;
运用系统动力学;
使用System.IO;
使用System.Linq;
运用系统反思;
使用Microsoft.CodeAnalysis;
使用Microsoft.CodeAnalysis.CSharp;
使用Microsoft.CSharp.RuntimeBinder;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
命名空间测试{
[测试类]
公共类FullExampleTest{
[测试方法]
公共无效硬编码(){
var map=newdictionary(){
{“你好”,“福”},
{“世界”,“酒吧”}
};
动态src=新的MyObject(贴图);
Console.WriteLine(src.Hello);
AreEqual(“foobar”,“$”{src.Hello}{src.World}”);
}
[测试方法]
public void CompileAtRuntime(){
字符串代码=@“
使用制度;
使用System.Collections.Generic;
使用System.Diagnostics.Contracts;
运用系统动力学;
使用System.IO;
使用System.Linq;
运用系统反思;
使用测试;
名称空间MyNamespace{{
公共类MyClass{{
公共静态无效MyMethod(MyObject src){{
Console.WriteLine(src.Hello);
}}
}}
}}
";
var ns=Assembly.Load(“netstandard,Version=2.0.0.0,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”);
MetadataReference[]引用=新MetadataReference[]
{
MetadataReference.CreateFromFile(ns.Location),//netstandard
MetadataReference.CreateFromFile(typeof(Object.Assembly.Location))//mscorlib
MetadataReference.CreateFromFile(typeof(DynamicObject).Assembly.Location),//System.Core
MetadataReference.CreateFromFile(typeof(RuntimeBinderException.Assembly.Location))//Microsoft.CSharp
MetadataReference.CreateFromFile(typeof(Action.Assembly.Location))//System.Runtime
MetadataReference.CreateFromFile(typeof(FullExampleTest).Assembly.Location)//此程序集
};
var comp=csharpcomilation.Create(
assemblyName:Path.GetRandomFileName(),
syntaxTrees:new[]{CSharpSyntaxTree.ParseText(code)},
参考文献:参考文献,
选项:新CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);
使用(var ms=new MemoryStream()){
var结果=组件发射(毫秒);
如果(!result.Success){
var failures=result.Diagnostics.Where(diagnostic=>diagnostic.IsWarningAsError | | | diagnostic.Severity==DiagnosticSeverity.Error);
foreach(故障诊断){
WriteLine($“{diagnostic.Id}-{diagnostic.GetMessage()}”);
}
}
Assert.IsTrue(result.Success,“编译失败…”);
}
}
}
公共类MyObject:DynamicObject{
私人词典地图;
公共MyObject(索引图){
_地图=地图;
}
公共重写bool TryGetMember(GetMemberBinder绑定器,输出对象结果){
Assert(binder!=null);
var ret=_Map.TryGetValue(binder.Name,out字符串值);
结果=值;
返回ret;
}
public override bool TryInvokeMember(InvokeMemberBinder绑定器,对象[]参数,输出对象结果){
Assert(binder!=null);
var ret=_Map.TryGetValue(binder.Name,out字符串值);
结果=值;
返回ret;
}
}
}

动态编译的代码与静态编译的代码不同。在动态编译的代码中,您已经显式地将
src
声明为
dynamic
。您的“硬编码”示例试图将is视为
MyObject
。如果您的硬编码测试如下所示,您也会遇到同样的问题:

    var src = new MyObject(map);
    Console.WriteLine(src.Hello);
因此,您可以通过将
src
强制转换为
dynamic
来解决此问题:

public static void MyMethod(MyObject src){
    Console.WriteLine(((dynamic)src).Hello);
}
或者首先将其声明为动态:

public static void MyMethod(dynamic src){
    Console.WriteLine(src.Hello);
}

也许这会对你有所帮助,所以我已经尝试了那篇文章中提到的所有东西。。你能更具体地说明我遗漏了什么吗?好的,非常感谢#把头撞在墙上这是看错地方的典型例子很高兴我能帮上忙。有时我们只需要一个朋友以全新的视角来看待代码。:-)