Roslyn动态类生成问题

时间:2018-01-22 12:19:58

标签: roslyn

所以我试图使用Roslyn创建一个动态类型(在运行时)。这个要求的整个背景太长了,无法进入。但是,我确实需要创建一个具有x个属性的新类型,我试图在字典中输入属性名称和初始值

以下是相关代码

private void CreateAssembly(Dictionary<string, string> propertiesToEmit)
{
    if (ourAssembly == null)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("using System;");
        sb.AppendLine("public class MyClass");
        sb.AppendLine("{");
        sb.AppendLine("  public static void Main()");
        sb.AppendLine("  {");
        sb.AppendLine("  }");
        foreach (var kvp in propertiesToEmit)
        {
            sb.AppendLine($"  public {kvp.Value} {kvp.Key}" + " { get; set; }");
        }
        sb.AppendLine("  public  MyClass CreateFromDynamic(Dictionary<string, object> sourceItem)");
        sb.AppendLine("  {");
        sb.AppendLine("     MyClass newOne = new MyClass();");
        foreach (var kvp in propertiesToEmit)
        {
            sb.AppendLine($@"  newOne.{kvp.Key} = sourceItem[""{kvp.Key}""];");
        }
        sb.AppendLine("  return newOne;");
        sb.AppendLine("  }");
        sb.AppendLine("}");

        var tree = CSharpSyntaxTree.ParseText(sb.ToString());
        var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
        var dictsLib = MetadataReference.CreateFromFile(typeof(Dictionary<,>).Assembly.Location);

        var compilation = CSharpCompilation.Create("MyCompilation",
            syntaxTrees: new[] { tree }, references: new[] { mscorlib, dictsLib });

        //Emit to stream
        var ms = new MemoryStream();
        var emitResult = compilation.Emit(ms);

        //Load into currently running assembly. Normally we'd probably
        //want to do this in an AppDomain
        ourAssembly = Assembly.Load(ms.ToArray());
    }
}

我在Roslyn中遇到这个奇怪的错误,它似乎无法找到对Dictionary&lt;,&gt;的引用。即使这是在 mscorlib 中引用的。

enter image description here

可以清楚地看到Dictionary&lt;,&gt;确实存在于被引用的dll(即 mscorlib )中。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

好的我找到了答案,我忘了在使用Roslyn创建的代码中添加这个using语句

sb.AppendLine("using System.Collections.Generic;");