在运行时转换为多个(未知类型)

我正在开发一个能够打开我们通过软件生成的所有自定义文档的查看器。 所有的文件都inheritance自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,但我认为它说明了我正在尝试做的事情。 什么是正确的方法去做?

编辑> @John好吧,也许我应该追加另一个问题:如果我有一个界面:

 public interface IDocument { public Int32 MyInt { get; } } 

和一个class级:

 public class SomeDocType : IDocument { protected Int32 myInt = 0; public Int32 MyInt { get { return myint; } } public Int32 DerivedOnlyInt; } 

如果我反序列化为IDocument,DerivedOnlyInt是否会成为对象的一部分 – 这样在反序列化之后,我可以转换为SomeDocType并且它会没事的?

为什么不直接转向IDocument ? 您认为铸造到确切类型会有什么好处?

如果你希望调用者以强类型的方式获得结果,那么我将使用generics来编写它:

 public T OpenDocument(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); } } 

编辑:要回答您的问题的编辑,是的派生属性仍然存在。 转换实际上并不会更改对象 – 它只是意味着您获得了编译器知道的适当类型的引用。

您正在使用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; } 

如果你可以很容易地弄清楚它是什么类型的文档(即:它是文件头的一部分),那么最简单的方法就是有一个特定于每种类型的反序列化策略 。