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

C# 如何使用Roslyn成功编译标记/标记的类,c#,attributes,roslyn,C#,Attributes,Roslyn,我正在处理一个客户,该客户希望将给定对象序列化/反序列化为XML,反之亦然。他不想用属性([XmlElement]、[XmlArray]等)标记所有类,这在我看来是最好的解决方案,所以他想用给定的对象生成一个动态类,这意味着,用相同的声明属性编写一个新类,并添加用于序列化的属性。新类是用StringBuilder编写的,之后必须编译它并获得一个新实例。问题是,如果我编写用于序列化的属性,这个新类不会编译,但是如果我删除这些属性,该类会成功编译,并且可以获得一个实例 这是密码 dynamicCla

我正在处理一个客户,该客户希望将给定对象序列化/反序列化为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 DefaultReferences=new[]{MetadataReference.CreateFromFile(string.Format(runtimePath,“System.Xml”),
MetadataReference.CreateFromFile(string.Format(运行时路径,“System.Xml.Serialization”),
MetadataReference.CreateFromFile(typeof(object.Assembly.Location)
};
csharpcomilation=csharpcomilation.Create(“DynamicCodeManager”,
新[]{syntaxTree},
默认引用,
新的CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
使用(var dllStream=new MemoryStream())
使用(var pdbStream=new MemoryStream())
{
var emitResult=compilation.Emit(dllStream,pdbStream);
如果(!emitResult.Success)
{
var diag=emitResult.Diagnostics;
}
其他的
{
dllStream.Seek(0,SeekOrigin.Begin);
Assembly=Assembly.Load(dllStream.ToArray());
列表类型声明=新列表(assembly.DefinedTypes);
类型Type=assembly.GetType(类型声明为[0].ToString());
dynamicObj=Activator.CreateInstance(类型);
}
}
我得到的信息如下:[0](7,8):错误CS0246:El nombre del tipo o del espacio de nombres'XmlElementAttributeAttribute'no se Enconcentroó(?falta una directiva using o una referencea de ensamblado?)Microsoft.CodeAnalysis.Diagnostic{Microsoft.CodeAnalysis.CSharp.CSDiagnostic}

有什么想法吗?
提前感谢。

关于这个具体问题:

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

这对我很有用:

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"))
            };

关于这个具体问题:

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

这对我很有用:

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"))
            };

关于你最初的问题:

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

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


关于您最初的问题:

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

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


[xmlementattribute]
需要是
[xmlement]
谢谢Markus,我复制了错误的代码。。。很抱歉对于[XmlElement]和[XmlArray],它不起作用。我刚刚编辑了上面的代码
[xmlementAttribute]
需要
[xmlementAttribute]
谢谢Markus,我复制了错误的代码。。。很抱歉对于[XmlElement]和[XmlArray],它不起作用。我刚刚编辑了上面的代码谢谢@NineBerry,它对我也有用。现在标记类编译。谢谢@NineBerry,它也对我有用。现在,标记类编译。