我可以“覆盖”派生类中 DataMember 的名称吗?

问题描述 投票:0回答:1

我必须实施一些协议。我需要序列化的所有 xml(WCF 合约)始终具有两个指定部分和一个“内容”部分 - 例如:

第一:

<X>
 <Y>
  <Content1/>
 </Y>
</X>

第二:

<X>
  <Y>
   <Content2/>
  </Y>
</X>

我想使用一些泛型,但随后出现了节点名称的问题。 我找到了这个答案:序列化 DataMember(名称)覆盖问题,但它不适合我。

我的方法的代码:

public class X<TContent>
{
     [DataMember]
     public Y<TContent> yName { get; set; }
}

public class Y<TContent>
{
     [DataMember]
     public virtual TContent Content { get; set; }
}

然后有一些“内容”类,例如:

public sealed class Content1Class: Y<Content1>
{
    [DataMember(Name = nameof(Content1))]
    public override Content1 Content { get; set; }
}

不幸的是,我的内容始终为空。

我的问题是: 我可以设置类之间的属性和关系来反序列化上述情况吗?也许我必须为每种内容类型创建单独的类?

c# xml datacontractserializer
1个回答
0
投票

您几乎明白了,并且

nameof
的想法将会奏效。其他一切都通过泛型类型约束和具有泛型属性的泛型类来解决。

考虑这个代码示例:

using System.Runtime.Serialization;
using FileStream = System.IO.FileStream;
using FileMode = System.IO.FileMode;

static class DefinitionSet {
    internal const string dataContractNamespace = 
        "https/www.my.site.org/contracts/demo";
    internal const string filename = "demo.xml";
} //DefinitionSet

[DataContract(Namespace = DefinitionSet.dataContractNamespace)]
public class X<ContentType> where ContentType : Content {
    [DataMember(Name = nameof(Y))]
    Y<ContentType> y = new();
    internal Y<ContentType> Y => y;
}

[DataContract(Namespace = DefinitionSet.dataContractNamespace)]
public class Y<ContentType> where ContentType : Content {
    [DataMember(Name = nameof(ContentType))]
    internal ContentType Content { get; set; }
} //Y

[DataContract(Namespace = DefinitionSet.dataContractNamespace)]
[KnownType(typeof(Content1))]
[KnownType(typeof(Content2))]
public abstract class Content {
} //Content

[DataContract(Namespace = DefinitionSet.dataContractNamespace)]
public class Content1 : Content {
    public Content1() { Index = 13; Message = nameof(Message); }
    [DataMember]
    internal int Index { get; private init; }
    [DataMember]
    internal string Message { get; private init; }
}
[DataContract(Namespace = DefinitionSet.dataContractNamespace)]

public class Content2 : Content {
    public Content2() {
        Comment = nameof(Comment);
        Topic = nameof(Topic);
    }
    [DataMember]
    internal string Comment { get; private init; }
    [DataMember]
    internal string Topic { get; private init; }
}

static class DataContractDemo {

    static void TestSerialization<ContentType>()
             where ContentType : Content, new() {
        X<ContentType> objectGraph = new();
        objectGraph.Y.Content = new ContentType();
        DataContractSerializer dcs = new(typeof(X<ContentType>));
        using var writeStream = new FileStream(
        $"{typeof(ContentType).Name}.{DefinitionSet.filename}",
            FileMode.Create);
        dcs.WriteObject(writeStream, objectGraph);
    } //TestSerialization

    static void Main() {
        TestSerialization<Content1>();
        TestSerialization<Content2>();
    } //Main

} //class DataContractDemo

我希望这个代码示例是自我记录的。如果有不清楚的地方,请进一步提问。

© www.soinside.com 2019 - 2024. All rights reserved.