Proto-buf .NET Сериализация сложных интерфейсов наследования - PullRequest
0 голосов
/ 04 февраля 2012

Я хотел бы сериализовать классы, которые реализуют несколько интерфейсов, некоторые из которых наследуются от одного базового интерфейса. В настоящее время я использую BinaryFormatter, но я бы хотел использовать Proto-Buf .NET. Но я думаю, что в настоящее время я столкнулся бы с проблемами, подобными этой описанной проблеме: как сериализовать класс реализует два интерфейса с одинаковым интерфейсом

Единственное возможное решение, о котором я сейчас думаю, - это обертка вокруг моих классов, которая сериализует более простой класс данных, который я использую для создания своих сложных классов.

Позвольте мне попытаться объяснить это далее, как в приведенном примере, у меня есть такая структура:

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 Ответ

1 голос
/ 07 февраля 2012

Звучит так, как будто вы идете на объединение типов . Вы хотите создать единый формат сериализации, подходящий для всех ваших продуктов. Кроме того, вы хотите, чтобы каждый из ваших продуктов отображался на этот тип объединения и возвращался обратно.

Так что вы по-прежнему беспокоитесь о том, как сделать отображение. Честно говоря, я не думаю, что в конечном итоге вы будете довольны этими двумя методами в интерфейсе IProduct. И я надеюсь, что вы знаете, что вам нужно решить проблему десериализации: какой тип вы на самом деле создаете? Позвольте мне выразить это следующим образом: с вашим кодом вам нужно будет вызвать новый ConcreteProduct (). BuildProduct (data), чтобы получить ваш 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": каким-то образом вы должны указать тип продукта в данных, чтобы узнать, какой тип продукта создать при сопоставлении с типом объединения.

Другая сложность, которую я вижу с типами объединения в целом, это де / сериализация графов объектов. Поскольку у вас есть свои собственные типы сериализации, вам нужно написать собственный код для де / составления графов объектов. Если вы новичок, как вы говорите, это, вероятно, поставит вас в мир боли (или мир обучения, если вы предпочитаете :-p).

В любом случае, действительно ли это должны быть интерфейсы, которые вы хотите де / сериализовать? Можно ли вместо этого создать иерархию классов, в которой вы начинаете с базового класса Product, из которого происходят все другие продукты и который содержит необходимые включения. Я предполагаю, что это создаст меньше проблем (по крайней мере, с protobuf).

И, наконец, главный вопрос: почему вы хотите точно перейти с BinaryFormatter на protobuf?

...