我正在开发一个通过Ninject使用依赖注入的项目。到目前为止,它运行得很好,我很喜欢DI,但现在我已经决定需要序列化一些对象,而且我发现在DI模式之后很难做到这一点。
假设我有一个名为Foo的类,它有一个Bars列表,并通过工厂生成它们,如下所示:
public class Foo
{
private List<Bar> _bars;
private BarFactory _barFactory;
...
public void MakeBar()
{
_bars.Add(_barFactory.MakeBar());
}
}
这是Bar,它是在调用_barFactory.MakeBar()
时生成的。我希望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
}
}
请注意,Bar有自己的工厂和一系列泡菜。这就是问题:当调用Bar的反序列化构造函数时,我没有办法让它获得另一个PickleFactory。最初的PickleFactory由BarFactory提供给Bar,但是BarFactory没有调用反序列化构造函数。
我目前解决这个问题的计划是将Bar的所有可序列化成员提取到它自己的名为BarDataObject的类中。然后我会使BarDataObject可序列化,但不是Bar本身。我会向BarFactory添加一个函数,它接受一个BarDataObject作为参数,并为你填充一个Bar,其中包含来自BarDataObject的所有信息。
但是,假设Pickle 还具有从制造它的工厂获得的服务类,它们也无法序列化。所以我也必须从Pickle中提取DataObject,而我的BarDataObject必须保留一个PickleDataObject。假设Pickle有一个成员变量,混合了数据和服务呢?我也必须为此创建和维护一个DataObject。这似乎是一个真正的无赖,特别是考虑到我的项目有许多其他我需要序列化的东西,他们可能会面临同样的问题。
那么有更好的解决方案吗?我做错了什么,DI明智吗?我刚刚开始使用DI和Ninject,但我似乎找不到任何人想出一个很好的方法来序列化注入了服务类的对象。
答案 0 :(得分:9)
根据我的经验,只有服务类应该具有依赖性,服务类永远不应该被序列化。
你有一个想要序列化的类但依赖于注入服务的类,这对我来说似乎是一种代码味道。
使用Bar
很难确切地告诉您要完成什么,但从我所看到的情况来看,我建议将Pickle
设为POCO并使用{{1}而不是自定义List<Pickle>
类。
或者,如果Bar
除了Pickles之外还要包含其他可序列化信息,请将Bar
作为带有Pickles属性的POCO:
Bar
因为POCO不具有依赖关系,所以它们不应该要求工厂,因此这个类应该是完全可序列化的。如果您希望在public class Bar
{
public string Name {get;set;}
public List<Pickle> Pickles {get;set;}
}
和Bar
上执行复杂的功能,则应将它们抽象为单独的实用程序服务,这些服务需要Pickle
和Bar
s作为他们的方法参数。