我正在为一个想要将给定对象序列化/反序列化为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}
有什么主意吗? 预先感谢。
答案 0 :(得分: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)
答案 1 :(得分:0)
关于您的原始问题:
首先,您不需要将类序列化为XML的属性。默认情况下,序列化程序将自动序列化所有公共属性和字段。仅当您想要偏离默认行为时,才需要使用属性来控制序列化。
但是,然后,您不需要在运行时创建动态类型来控制XML序列化。您可以使用XmlAttributeOverrides
类来模拟具有xml序列化控件属性的特定类型,如文档中所述: