我正在研究一个想要将给定对象序列化/反序列化为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}
任何的想法?提前致谢。
关于这个具体问题:
您需要确保包含所有必需的引用,并且所有引用都来自同一个运行时(目录)。
这对我有用:
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)
关于你原来的问题:
首先,您不需要将类序列化为XML的属性。默认情况下,序列化程序会自动序列化所有公共属性和字段。只有在想要偏离默认行为时,才需要使用属性来控制序列化。
但是,您也不需要在运行时创建动态类型来控制XML序列化。您可以使用XmlAttributeOverrides
类来模拟具有xml序列化控制属性的特定类型,如文档中所述: