简体   繁体   English

如何序列化工厂创建的对象

[英]How to serialize objects created by factories

I'm working on a project that uses dependency injection via Ninject. 我正在开发一个通过Ninject使用依赖注入的项目。 So far, it is working out very well, and I'm liking DI a lot, but now I have decided I need to serialize some objects, and I'm finding it difficult to do that following DI patterns. 到目前为止,它运行得很好,我很喜欢DI,但现在我已经决定需要序列化一些对象,而且我发现在DI模式之后很难做到这一点。

Say I have a class called Foo, which has a list of Bars, and makes them through a factory, like this: 假设我有一个名为Foo的类,它有一个Bars列表,并通过工厂生成它们,如下所示:

public class Foo
{
    private List<Bar> _bars;
    private BarFactory _barFactory;

    ...

    public void MakeBar()
    {
         _bars.Add(_barFactory.MakeBar());
    }
}

Here's Bar, which gets made when _barFactory.MakeBar() gets called. 这是Bar,它是在_barFactory.MakeBar()_barFactory.MakeBar() I want Bar to be serializable: 我希望Bar可序列化:

public class Bar : ISerializable
{
    private List<IPickle> _pickles;
    private PickleFactory _pickleFactory;

    public Bar(PickleFactory factory)
    {
         _pickleFactory = factory;
    }

    public void MakePickle(int x)
    {
         _pickles.Add(_pickleFactory.MakePickle(x));
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        //serialize member variables here
    }

    //Constructor called during deserialization
    private Bar(SerializationInfo info, StreamingContext context)
    {
        //fill in member variables with data from SerializationInfo
    }
}

Notice that Bar has its own factory and a collection of pickles. 请注意,Bar有自己的工厂和一系列泡菜。 Here's the problem: when the deserialization constructor of Bar gets called, I don't have any way to get it another PickleFactory. 这就是问题:当调用Bar的反序列化构造函数时,我没有办法让它获得另一个PickleFactory。 The original PickleFactory was given to Bar by the BarFactory, but the deserialization constructor wasn't called by BarFactory. 原始的PickleFactory由BarFactory提供给Bar,但是反序列化构造函数没有被BarFactory调用。

My current plan to solve this problem would be to extract all the serializable members of Bar into its own class called BarDataObject. 我目前解决这个问题的计划是将Bar的所有可序列化成员提取到它自己的名为BarDataObject的类中。 Then I would make the BarDataObject serializable, but not Bar itself. 然后我会使BarDataObject可序列化,但不是Bar本身。 I would add a function to BarFactory which accepts a BarDataObject as a parameter and builds a Bar for you filled in with all the information from the BarDataObject. 我会向BarFactory添加一个函数,它接受一个BarDataObject作为参数,并为你填充一个Bar,其中包含来自BarDataObject的所有信息。

However, suppose Pickle also has service classes which it got from the factory that made it, which can't be serialized either. 但是,假设Pickle 还有从制造它的工厂获得的服务类,它们也无法序列化。 So I would have to extract a DataObject from Pickle as well, and my BarDataObject would have to hold onto a PickleDataObject. 所以我也必须从Pickle中提取DataObject,而我的BarDataObject必须保留一个PickleDataObject。 And suppose Pickle had a member variable with a mix of data and services too? 假设Pickle有一个成员变量,混合了数据和服务呢? I would have to make and maintain a DataObject for that as well. 我也必须为此创建和维护一个DataObject。 This seems like a real bummer, especially considering my project has many other things which I need to serialize, and they'll probably face the same problem. 这似乎是一个真正的无赖,特别是考虑到我的项目有许多其他我需要序列化的东西,他们可能会面临同样的问题。

So is there a better solution? 那么有更好的解决方案吗? Am I doing something wrong, DI-wise? 我做错了什么,DI明智吗? I've just started working with DI and Ninject, but I can't seem to find anyone who's come up with a good way to serialize objects which got injected with service classes. 我刚刚开始使用DI和Ninject,但我似乎找不到任何人想出一个很好的方法来序列化注入了服务类的对象。

In my experience, only service classes should have dependencies, and service classes should never be subject to serialization. 根据我的经验,只有服务类应该具有依赖性,而服务类永远不应该进行序列化。

The fact that you have a class that you want to serialize, but which relies on an injected service, seems like a code smell to me. 你有一个想要序列化的类,但依赖于注入服务的类,这对我来说似乎是一种代码味道。

It's difficult to tell exactly what you're trying to accomplish with Bar , but from what I can see, I'd suggest making Pickle be a POCO, and using a List<Pickle> instead of a custom Bar class. 很难准确地告诉你要用Bar完成什么,但从我所看到的,我建议将Pickle变为POCO,并使用List<Pickle>而不是自定义Bar类。

Or, if Bar is intended to have other serializable information besides the Pickles, make Bar a POCO with a Pickles property: 或者,如果Bar除了Pickles之外还有其他可序列化信息,请使Bar成为具有Pickles属性的POCO:

public class Bar
{
    public string Name {get;set;}
    public List<Pickle> Pickles {get;set;}
}

Because POCOs won't have dependencies, they shouldn't require factories, so this class should be entirely serializable. 因为POCO不具有依赖性,所以它们不应该要求工厂,因此该类应该是完全可序列化的。 If there are complex functions that you'd like to perform on Bar s and Pickle s, they should be abstracted out into separate utility services that take Bar s and Pickle s as their method parameters. 如果您希望在BarPickle上执行复杂的功能,则应将它们抽象为单独的实用程序服务,这些服务将Bar s和Pickle作为其方法参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM