在XmlSerializer上装饰Xml ClassName

本文关键字:Xml ClassName XmlSerializer | 更新日期: 2023-09-27 18:28:34

我需要获得以下xml:

<request id="1">
  <login>
    <username>username</username>
    <password>password</password>
  </login>
</request>

但是中间的xml可以更改为另一种类型的请求,如

<request id="1">
  <logout />
</request>

我尝试了以下方法:

[XmlRootAttribute(ElementName = "request", Namespace = "", IsNullable = false)]
public class Request<T>
{
    [XmlAttributeAttribute(AttributeName = "id", Namespace = "")]
    public string Id { get; set; }
    public T Content { get; set; }
}
[XmlTypeAttribute(TypeName = "login", AnonymousType = true)]
public class LoginRequest
{
    [XmlElementAttribute(ElementName = "username", Namespace = "")]
    public string Username;
    [XmlElementAttribute(ElementName = "password", Namespace = "")]
    public string Password;
}
[XmlTypeAttribute(TypeName = "logout", AnonymousType = true)]
public class LogoutRequest
{
}

但是当我使用序列化对象时

var serializer = new XmlSerializer(typeof(Request<LoginRequest>));

我得到了以下xml:

<request id="1">
  <Content>
    <username>username</username>
    <password>password</password>
  </Content>
</request>

如何将标记Content重命名为登录或注销?

非常感谢

在XmlSerializer上装饰Xml ClassName

假设您知道所有可能的请求类型,您可以使用XmlElement(name, Type)构造函数来覆盖特定类型的属性名称:

[XmlRoot(ElementName = "request", Namespace = "", IsNullable = false)]
public class Request
{
    [XmlAttributeAttribute(AttributeName = "id", Namespace = "")]
    public string Id { get; set; }
    [XmlElement("login", Type = typeof(LoginRequestData))]
    [XmlElement("logout", Type = typeof(LogoutRequestData))]
    public BaseRequestData RequestData { get; set; }
    public TRequestData GetRequestData<TRequestData>() where TRequestData : BaseRequestData
    {
        return RequestData as TRequestData;
    }
}
public abstract class BaseRequestData
{
}
public class LoginRequestData : BaseRequestData
{
    [XmlElementAttribute(ElementName = "username", Namespace = "")]
    public string Username;
    [XmlElementAttribute(ElementName = "password", Namespace = "")]
    public string Password;
}
public class LogoutRequestData : BaseRequestData
{
}
public class SomeUnknownRequestData : BaseRequestData
{
}

而且,要测试:

    public static void LoginRequestTest()
    {
        try
        {
            var request1 = new Request() { RequestData = new LoginRequestData() { Username = "foo", Password = "bar" } };
            var request2 = new Request() { RequestData = new LogoutRequestData() };
            var request3 = new Request() { RequestData = new SomeUnknownRequestData() };
            var xml1 = request1.GetXml();
            var xml2 = request2.GetXml();
            try
            {
                var xml3 = request3.GetXml(); // Throws an exception.
            }
            catch (InvalidOperationException ex2)
            {
                Debug.WriteLine(ex2.ToString());
            }
        }
        catch (Exception ex)
        {
            Debug.Assert(false, ex.ToString()); // No assert
        }
    }

xml1看起来像:

<?xml version="1.0" encoding="utf-16"?>
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <login>
        <username>foo</username>
        <password>bar</password>
    </login>
</request>

xml2看起来像:

<?xml version="1.0" encoding="utf-16"?>
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <logout />
</request>

这是你想要的吗?为了简单起见,我去掉了请求的通用性。