如何使用Roslyn成功编译标记/标记的类

问题描述 投票:1回答:2

我正在研究一个想要将给定对象序列化/反序列化为XML的客户,反之亦然。他不会用属性([XmlElement],[XmlArray]等)来标记他的所有类,这在我看来是最好的解决方案,所以他想用给定的对象生成动态类,这意味着,写具有相同声明属性的新类,并添加序列化的属性。新类使用StringBuilder编写,稍后必须编译并获取新实例。问题是,如果我编写序列化的属性,这个新类不会编译,但如果我删除属性,该类编译成功,我可以得到一个实例。

这里的代码

dynamicClassCode = @"
using System.Xml.Serialization;

namespace Pat.Infrastructure.Communication.Model
{
   public class RequestMessage_Serializable
   {
      [XmlElement]
      public System.DateTime RequestDateTime { get; set; }

      [XmlElement]  
      public System.String RequestUniqueMessageId { get; set; }

      [XmlElement]  
      public System.Version Version { get; set; }

      [XmlElement]  
      public System.String User { get; set; }

      [XmlElement]  
      public System.String Password { get; set; }

      [XmlElement]
      public System.String Terminal { get; set; }

      [XmlElement]
      public System.String Method { get; set; }

      [XmlElement]
      public System.Object Request { get; set; }

      [XmlElement]
      public System.String RequestType { get; set; }

      [XmlElement]
      public System.String EndPointSource { get; set; }

      [XmlElement]
      public System.String ResponseFormatExpected { get; set; }

      [XmlElement]
      public System.Object Configuration { get; set; }

      [XmlElement]
      public System.Boolean OneWay { get; set; }
   }
}"

string runtimePath = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5\{0}.dll";
var syntaxTree = CSharpSyntaxTree.ParseText(dynamicClassCode);

IEnumerable<MetadataReference> DefaultReferences = new[] {MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml")),
                        MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.Serialization")),
                        MetadataReference.CreateFromFile(typeof(object).Assembly.Location)
                        };

CSharpCompilation compilation = CSharpCompilation.Create("DynamicCodeManager",
                new[] { syntaxTree },
                DefaultReferences,
                new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

using (var dllStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
  var emitResult = compilation.Emit(dllStream, pdbStream);
  if (!emitResult.Success)
  {
    var diag = emitResult.Diagnostics;
  }
  else
  {
    dllStream.Seek(0, SeekOrigin.Begin);
    Assembly assembly = Assembly.Load(dllStream.ToArray());
   List<System.Reflection.TypeInfo> typesDeclared = new List<System.Reflection.TypeInfo>(assembly.DefinedTypes);
                    Type type = assembly.GetType(typesDeclared[0].ToString());
                    dynamicObj = Activator.CreateInstance(type);
  }
}

我收到的消息如下:[0](7,8):错误CS0246:找不到类型或命名空间“XmlElementAttributeAttribute”的名称(使用指令或程序集引用是否缺少?)Microsoft。 CodeAnalysis.Diagnostic {Microsoft.CodeAnalysis.CSharp.CSDiagnostic}

任何的想法?提前致谢。

c# attributes roslyn
2个回答
0
投票

关于这个具体问题:

您需要确保包含所有必需的引用,并且所有引用都来自同一个运行时(目录)。

这对我有用:

IEnumerable<MetadataReference> DefaultReferences = new[] {
            MetadataReference.CreateFromFile(string.Format(runtimePath, "mscorlib")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Runtime")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.Serialization")),
            MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Xml.XmlSerializer"))
            };

请注意,您拥有的以下代码很可能从“runtimePath”以外的其他目录加载mscorlib程序集,从而加载不兼容的程序集。

MetadataReference.CreateFromFile(typeof(object).Assembly.Location)

0
投票

关于你原来的问题:

首先,您不需要将类序列化为XML的属性。默认情况下,序列化程序会自动序列化所有公共属性和字段。只有在想要偏离默认行为时,才需要使用属性来控制序列化。

但是,您也不需要在运行时创建动态类型来控制XML序列化。您可以使用XmlAttributeOverrides类来模拟具有xml序列化控制属性的特定类型,如文档中所述:

XmlAttributeOverrides Class

© www.soinside.com 2019 - 2024. All rights reserved.