使用 DataContractSerializer 序列化子类实例的实用方法是什么?



使用DataContractSerializer序列化子类实例的实用方法是什么?

例如,以下是数据类型:

 [DataContract]
    public class Car
    {
        public Car()
        {
            Wheels = new Collection<Wheel>();
        }
        [DataMember]
        public Collection<Wheel> Wheels { get; set; }
    }
    [DataContract]    
    public abstract class Wheel
    {
        [DataMember]
        public string Name { get; set; }
    }
    [DataContract]
    public class MichelinWheel : Wheel
    {
        [DataMember]
        public string Wheel1Test { get; set; }
    }
    [DataContract]
    public class BridgeStoneWheel : Wheel
    {
        [DataMember]
        public string Wheel2Test { get; set; }
    }

下面是创建一辆有两个不同车轮的汽车的代码:

    Car car = new Car();
    MichelinWheel w1 = new MichelinWheel { Name = "o1", Wheel1Test = "o1 test" };
    BridgeStoneWheel w2 = new BridgeStoneWheel { Name = "o2", Wheel2Test = "o2 test" };
    car.Wheels.Add(w1);
    car.Wheels.Add(w2);

现在,如果我尝试使用DataContractSerializer来序列化汽车,我会得到一个异常,说MichelWhereel不是预期的。我必须像这样修改Wheel类才能使其工作:

 [DataContract]
    [KnownType(typeof(MichelinWheel))]
    [KnownType(typeof(BridgeStoneWheel))]
    public abstract class Wheel
    {
        [DataMember]
        public string Name { get; set; }
    }

但这种方法并不实用,因为我无法在创建各种轮子之前列出它们。每次创建新品牌的轮子后更改轮子类也是不现实的,因为它们可能是在第三方代码中创建的。

那么,当使用DataContractSerializer时,序列化子类实例的实用方法是什么呢?

感谢

使用WCF 4中的DataContractResolver查看本文。您还可以将KnownTypeAttribute与将使用反射获取所有类型的方法的传递名称一起使用。无论如何,服务要求在启动之前知道所有类型。

有几种方法可以使已知类型可用于服务。

上面概述了最简单的方法,但很明显,这需要在添加新类型时重新编译,而且根据您的配置,避免循环依赖关系可能会很困难。

您还可以配置KnownTypes:

  • 通过服务配置文件(只需要重新启动服务)
  • 将它们添加为通过服务接口上的静态方法提供的服务已知类型,正如Ladislav Mrnka所指出的,您可以通过反射获得该类型(您可能可以反射所有加载的程序集,并将其上具有DataContact属性的所有类型返回为已知类型,但我找不到这样的示例。)
  • 实现您自己的获取方式(可能通过配置文件中的一些定制配置元素,也可能只是通过文本文件)

相关内容

最新更新