Proto-buf .NET复杂继承接口的序列化

时间:2012-02-04 17:50:55

标签: c# protobuf-net

我想序列化实现多个接口的类,这些接口从同一个基接口继承。目前我使用BinaryFormatter,但我很想使用proto-buf .NET。但我认为目前我将遇到与此描述问题类似的问题: how to serialize a class implements two interfaces who have same based interface

我目前认为唯一可行的解​​决方案是我的类的包装器,它序列化一个更简单的数据类,用于创建我的复杂类。

让我试着进一步解释,就像在引用的例子中我有这样的结构:

public interface IProduct
{ 
    string SomeMethod(); 
}

public interface ISimpleProduct : IProduct
{ 
    int SomeProperty { get; } 
}

public interface IConstructionProduct : IProduct
{
    int AnotherProperty {get; 
}

public class ConcreteProduct : ISimpleProduct , IConstructionProduct
{
     int SomeProperty {get; set;}
     int AnotherProperty {get; set;}

     string SomeMethod()
     {
           return "A concrete Product";
     }
}

现在我希望序列化ConcreteProduct,因为我认为目前在proto-buf .net中这是不可能的,我正在考虑有一个包装器数据类,如下所示:

public class ProductData
{
    int[] PropertyValues { get; set;}
}

并向IProductInterface添加一个构建每个具体产品的方法,例如

public interface IProduct
{
      string SomeMethod();
      IProduct BuildProduct(ProductData data);
      ProductData ToData();
}

当然,ProductData在现实中会更复杂,但仅限于概念。我现在将序列化ProductData。我不想更改Product ConcreteProduct类中的接口设置,因为稍后需要这些接口以供进一步使用。我喜欢这种方法,扩展问题可以在BuildProduct实现中处理。 再一次,我是一个新手,所以如果有什么只是简单的废话,抱歉并纠正我。

@ Marc,我知道你是作者,对于那些东西很多,但更多其他帖子(我还没有使用proto-buf),例如在DataTable的东西上,已经关于自动生成列的帖子已经保存了我有很多时间。

1 个答案:

答案 0 :(得分:1)

这听起来像是你要采用union types方法。您希望制作适合所有产品的单一序列化格式。此外,您希望每个产品都映射到该联合类型并映射回来。

所以你仍然关注如何进行映射。老实说,从长远来看,我不认为你会在IProduct界面中使用这两种方法。我希望你知道你需要处理反序列化的问题:你实际实例化了哪种类型?让我这样说吧:使用您的代码,您将不得不调用新的ConcreteProduct()。BuildProduct(数据)来获取您的ConcreteProduct。问题是:你怎么知道它是一个你必须实例化的ConcreteProduct?想要调用BuildProduct的代码需要知道这个!您可以删除这些方法并为映射任务创建单独的基础结构。以下是这种问题的工厂方法模式:

public interface IProductMapper {
  IProduct Unmap(ProductData data);
  ProductData Map(IProduct product);
}

public static class ProductMapperFactory {
  public static IProductMapper GetMapper(ProductData data) {
    if (data.Type == "ConcreteProduct") return new ConcreteProductMapper();
    else if ...
  }

  public static IProductMapper GetMapper(IProduct product) {
    if (product is ConcreteProduct) return new ConcreteProductMapper();
    else if ...
  }
}

public class ConcreteProductMapper : IProductMapper {
  public IProduct Unmap(ProductData data) {
    var product = new ConcreteProduct();
    // map properties
    return product;
  }

  public ProductData Map(IProduct data) {
    var data = new ProductData();
    // map data
    return data;
  }
}

你知道,关键的一行是data.Type == "ConcreteProduct":不知何故,你必须在数据中指定产品的种类,以便知道在从联合类型映射回来时要实例化哪种产品。

我在联合类型中看到的另一个困难是对象图的de /序列化。由于您有自己的序列化类型,因此需要编写自己的代码来编写对象图。如果你是一个新手,就像你说的那样,这可能会让你进入一个受伤的世界(如果你愿意的话,还是学习的世界:-p)。

在任何情况下,它真的需要是你要取消/序列化的接口吗?是否有可能创建一个类层次结构,您可以从Product基类开始,所有其他产品都从该基类派生并带有必要的包含。我认为这会减少麻烦(至少使用protobuf)。

最后,主要问题:为什么要完全从BinaryFormatter切换到protobuf?