我正在开发一个能够打开我们通过软件生成的所有自定义文档的查看器。所有文件都继承自IDocument,但我不确定如何进行反序列化(以一种好的方式 - 嵌套的try / catch可能会起作用,但这样做会很可怕)。
所以我的方法现在看起来像这样:
public Boolean OpenDocument(String filename, Type docType, out IDocument document)
{
// exception handling etc. removed for brevity
FileStream fs = null;
BinaryFormatter bFormatter = new BinaryFormatter();
fs = new FileStream(filename, FileMode.Open);
document = (docType)bFormatter.Deserialize(fs);
return true;
}
显然这不起作用,因为我不能以这种方式使用变量docType,但我认为它说明了我正在尝试做的事情。什么是正确的方法呢?
编辑> @约翰 好吧,也许我应该追加另一个问题: 如果我有一个界面:
public interface IDocument
{
public Int32 MyInt { get; }
}
和一个班级:
public class SomeDocType : IDocument
{
protected Int32 myInt = 0;
public Int32 MyInt { get { return myint; } }
public Int32 DerivedOnlyInt;
}
如果我反序列化为IDocument,DerivedOnlyInt是否会成为对象的一部分 - 这样在反序列化之后,我可以转换为SomeDocType并且它会没事?
答案 0 :(得分:4)
为什么不直接投放到IDocument
?你认为铸造到确切类型会有什么好处呢?
如果您希望调用者以强类型方式获得结果,请使用泛型来编写它:
public T OpenDocument<T>(String filename) where T : IDocument
{
using (FileStream fs = new FileStream(filename, FileMode.Open))
{
BinaryFormatter bFormatter = new BinaryFormatter();
return (T) bFormatter.Deserialize(fs);
}
}
当然,这依赖于调用者在编译时知道正确的类型。如果他们不这样做,他们就无法知道如何使用正确的类型,所以只需返回IDocument
:
public IDocument OpenDocument(String filename)
{
using (FileStream fs = new FileStream(filename, FileMode.Open))
{
BinaryFormatter bFormatter = new BinaryFormatter();
return (IDocument) bFormatter.Deserialize(fs);
}
}
编辑:要回答您的问题的编辑,是的,派生属性仍然存在。转换实际上并不会更改对象 - 它只是意味着您获得了编译器知道的适当类型的引用。
答案 1 :(得分:1)
您正在使用BinaryFormatter类,其中包含序列化流中的类型信息,因此您不需要docType变量:
public Boolean OpenDocument(String filename, out IDocument document)
{
// exception handling etc. removed for brevity
FileStream fs = null;
BinaryFormatter bFormatter = new BinaryFormatter();
fs = new FileStream(filename, FileMode.Open);
document = (IDocument)bFormatter.Deserialize(fs);
return true;
}
答案 2 :(得分:1)
如果您可以轻松找出它是什么类型的文档(即:它是文件头的一部分),最简单的方法是使用strategy反序列化特定于每种类型。