复杂继承接口的Proto-buf.NET序列化
本文关键字:NET 序列化 Proto-buf 继承 接口 复杂 | 更新日期: 2023-09-27 18:22:35
我想序列化那些实现了几个接口的类,其中一些接口继承自同一个基本接口。目前我使用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,因为我认为这在protobuf.net中是不可能的,我正在考虑有一个包装器数据类,比如:
public class ProductData
{
int[] PropertyValues { get; set;}
}
并在IProductInterface中添加一种构建每个具体产品的方法,如
public interface IProduct
{
string SomeMethod();
IProduct BuildProduct(ProductData data);
ProductData ToData();
}
当然,ProductData在现实中会更复杂,但只是为了概念。我现在要序列化ProductData。我不想更改ProductConcreteProduct类中的接口设置,因为这些接口是以后需要的。我喜欢这种方法的原因是,扩展问题可以在BuildProduct实现中处理。再说一次,我是一个新手,所以如果有什么纯属无稽之谈,请原谅并纠正我。
@Marc,我知道你是作者,这方面的文章很多,但其他帖子(我还没有使用proto-buf)更多,比如DataTable的文章,你关于自动生成列的帖子已经为我节省了很多时间。
这听起来像是在采用联合类型方法。您希望制作一个适合所有产品的单一序列化格式。此外,您希望您的每个产品都映射到该联合类型并映射回。
因此,您仍然关心的是如何进行映射。老实说,从长远来看,我认为您不会对IProduct接口中的这两个方法感到满意。我希望您知道您需要处理反序列化的问题:您实际实例化的是哪种类型?让我这样说:使用您的代码,您必须调用new ConcreteProduct().BuildProduct(data)才能获得您的ConcretePproduct。问题是:你怎么知道它是一个必须实例化的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
基类开始,所有其他产品都从该基类派生,并携带必要的include。我想这会减少麻烦(至少对protobuf来说)。
最后,主要问题是:为什么你想从BinaryFormatter切换到protobuf?