【问题标题】:Xml-attributes in interfaces and abstract classes接口和抽象类中的 XML 属性
【发布时间】:2012-10-22 08:32:30
【问题描述】:

我今天发现了一些让我感到困惑的事情:

1. 如果我有这个:

public interface INamed
{
    [XmlAttribute]
    string Name { get; set; }
}

public class Named : INamed
{
    public string Name { get; set; }
}

它给出以下输出(名称属性序列化为元素):

<Named>
  <Name>Johan</Name>
</Named>

2. 如果我有这个:

public abstract class NamedBase
{
    [XmlAttribute]
    public abstract string Name { get; set; }
}

public class NamedDerived : NamedBase
{
    public override string Name { get; set; }
}

XmlSerializer 抛出 System.InvalidOperationException

成员“NamedDerived.Name”隐藏继承的成员“NamedBase.Name”, 但有不同的自定义属性。

我用于序列化的代码:

[TestFixture] 
public class XmlAttributeTest
{
    [Test]
    public void SerializeTest()
    {
        var named = new NamedDerived {Name = "Johan"};
        var xmlSerializer = new XmlSerializer(named.GetType());
        var stringBuilder = new StringBuilder();
        using (var stringWriter = new StringWriter(stringBuilder))
        {
            xmlSerializer.Serialize(stringWriter, named);
        }
        Console.WriteLine(stringBuilder.ToString());
    }
}

我的问题是:

我做错了吗?如果是,在接口和抽象类中使用 xml 属性的正确方法是什么?

【问题讨论】:

    标签: c# interface xml-serialization abstract custom-attributes


    【解决方案1】:

    属性不会在被覆盖的属性上继承。你需要重新声明它们。 同样在您的第一个示例中,行为不是您在接口级别声明 XmlAttribute 时的“预期”行为,但序列化的 xml 包含作为元素的值。所以接口中的属性被忽略,只有从实际类中获取的信息才重要。

    【讨论】:

    • 将此标记为答案,猜想我真正的问题是为什么允许在接口和抽象类上声明属性。也许这只是属性使用控制细粒度的限制。
    • 你可以在任何你喜欢的地方声明它们,只要读回它们的代码知道这一点。在这种情况下,序列化程序必须检查类定义,然后检查所有实现的属性接口。至于属性使用;在这种情况下,它被定义为 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue)]。属性意味着任何属性,并且 ClassOnlyProperty 不存在作为可能的限制(我不确定它是否有用)。
    • 在某些时候您需要阅读文档。并非所有行为都可以描述为语法限制,也不应该是
    【解决方案2】:

    我认为你应该 xmlignore 你的抽象类属性

    public abstract class NamedBase
    {
        [XmlIgnore]
        public abstract string Name { get; set; }
    }
    
    public class NamedDerived : NamedBase
    {
        [XmlAttribute]
        public override string Name { get; set; }
    }
    

    【讨论】:

    • 这对我帮助很大;出于某种原因,序列化程序也希望显式处理基类,而我特别打算不知道底层存储机制......
    • 我试图使用带有 XmlIgnore 属性的 'Specified' 属性来忽略空列表的序列化,并且只有在抽象属性带有 'XmlIgnore'
    猜你喜欢
    • 2013-12-31
    • 2011-01-09
    • 2019-01-09
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多