该属性未包含在生成的代理类中
时间:2020-03-06 14:59:41 来源:igfitidea点击:
使用.Net 3.0和VS2005.
有问题的对象从WCF服务中使用,然后序列化回XML以用于旧版API。因此,与其序列化TestObject,不如序列化.TestObject,它缺少[XmlRoot]属性。但是,子元素的所有[Xml *]属性都在生成的代理代码中,因此它们工作正常。因此,所有的子元素都可以正常工作,但是封闭的元素却没有,因为[XmlRoot]属性未包含在生成的代理代码中。包含[XmlRoot]属性的原始对象可以手动进行很好的序列化。
我是否可以让代理代码包含[XmlRoot]属性,以便生成的代理类也可以正确序列化?如果我无法做到这一点,我怀疑我将不得不使用[XmlType],但是这会造成严重的破坏,需要我更改其他组件,因此我希望使用前者。我还希望避免手动编辑自动生成的代理类。
这是一些示例代码(我将客户端和服务包含在同一个应用程序中,因为这是快速且出于测试目的。注释掉服务引用代码,并在运行应用程序时添加服务引用,然后取消注释服务代码并运行)
namespace SerializationTest { class Program { static void Main( string[] args ) { Type serviceType = typeof( TestService ); using (ServiceHost host = new ServiceHost( serviceType, new Uri[] { new Uri( "http://localhost:8080/" ) } )) { ServiceMetadataBehavior behaviour = new ServiceMetadataBehavior(); behaviour.HttpGetEnabled = true; host.Description.Behaviors.Add( behaviour ); host.AddServiceEndpoint( serviceType, new BasicHttpBinding(), "TestService" ); host.AddServiceEndpoint( typeof( IMetadataExchange ), new BasicHttpBinding(), "MEX" ); host.Open(); TestServiceClient client = new TestServiceClient(); localhost.TestObject to = client.GetObject(); String XmlizedString = null; using (MemoryStream memoryStream = new MemoryStream()) { XmlSerializer xs = new XmlSerializer( typeof( localhost.TestObject ) ); using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream)) { xs.Serialize( xmlWriter, to ); memoryStream = (MemoryStream)xmlWriter.BaseStream; XmlizedString = Encoding.UTF8.GetString( memoryStream.ToArray() ); Console.WriteLine( XmlizedString ); } } } Console.ReadKey(); } } [Serializable] [XmlRoot( "SomethingElse" )] public class TestObject { private bool _worked; public TestObject() { Worked = true; } [XmlAttribute( AttributeName = "AttributeWorked" )] public bool Worked { get { return _worked; } set { _worked = value; } } } [ServiceContract] public class TestService { [OperationContract] [XmlSerializerFormat] public TestObject GetObject() { return new TestObject(); } } }
这是生成的Xml。
<?xml version="1.0" encoding="utf-8"?> <TestObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" AttributeWorked="true" />
解决方案
我发现有人提供了解决这种情况的方法:
Matevz Gacnik的博客
使用" XmlAttributeOverrides"的方法,我编写了以下代码:
private static XmlSerializer GetOverridedSerializer() { // set overrides for TestObject element XmlAttributes attrsTestObject = new XmlAttributes(); XmlRootAttribute rootTestObject = new XmlRootAttribute("SomethingElse"); attrsTestObject.XmlRoot = rootTestObject; // create overrider XmlAttributeOverrides xOver = new XmlAttributeOverrides(); xOver.Add(typeof(localhost.TestObject), attrsTestObject); XmlSerializer xSer = new XmlSerializer(typeof(localhost.TestObject), xOver); return xSer; }
只需将该方法放在示例的Program类中,然后在Main()中替换以下行即可:
//XmlSerializer xs = new XmlSerializer(typeof(localhost.TestObject)); XmlSerializer xs = GetOverridedSerializer();
然后运行以查看结果。
这是我得到的:
<?xml version="1.0" encoding="utf-8"?><SomethingElse xmlns:xsi="http://www.w3.o rg/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Attribu teWorked="true" />
== IF ==
这仅适用于XmlRoot
属性。 XmlSerializer具有一个构造函数,我们可以在其中指定XmlRoot属性。
感谢csgero指出它。他的评论应该是解决方案。
XmlSerializer Constructor (Type, XmlRootAttribute)
Initializes a new instance of the XmlSerializer class that can serialize objects of the specified type into XML documents, and deserialize an XML document into object of the specified type. It also specifies the class to use as the XML root element.