2015-02-07 29 views
0

给出下面的示例代码,我想要在一个泛型方法中获取T的运行时类型(在本例中为retrieveData)。当我创建一个XMLFilePersisting我使用的接口,即ITransferable而不是实现类型,因为在我的客户我想拥有所有这些列表一起:获得运行时间的最佳方式T的类型?

List<XMLFilePersisting<ITransferable>> allThem; 

因此,如果retrieveData我做的typeof(T)那应该返回ITransferable,它不会给我足够的信息来加载文件中的项目。我可以想出如何做到这一点的唯一方法是通过在构造函数中传递ITransferable的实现者实例,但是这种感觉应该有更好的方式。建议?

public interface IPersisting<T> { 
     List<T> retrieveData(); 
     bool persistData(List<T> lst); 
    } 

public interface ITransferable { 
    Type getRuntimeType(); 
} 

public class XMLFilePersisting<T> : IPersisting<T> where T : ITransferable { 
    private readonly T defaultT; 
    //... 
    public XMLFilePersisting(string thefile, string thepath, T def) { 
     //... 
     defaultT = def; 
    } 
    ... 

    public List<T> retrieveData() { 
     List<T> retVal = new List<T>(); 
     Type runType = defaultT.getRuntimeType(); 
     string elemName = runType.Name; 
     using (FileStream fs = new FileStream(FQ_FILE_PATH, FileMode.Open, FileAccess.Read)) { 
     using (XmlReader reader = XmlReader.Create(fs)) { 
      //below line won't work, typeof resolves at compileTime  
      //XmlSerializer xmlSer = new XmlSerializer(typeof(T)); 
      XmlSerializer xmlSer = new XmlSerializer(runType); 
      if (reader.ReadToFollowing(elemName)) { //go to the first test, skipping over ListofT 
       do { 
       T testVal = (T)xmlSer.Deserialize(reader); 
       retVal.Add(testVal); 
       } 
       while (reader.ReadToNextSibling(elemName)); 
      } 
     } //end using xmlreader 
     } //end using FileStream 
    return retVal; 
    } //end retrieveData 
} //end class XMLFilePersisting 

附加信息:

客户端的代码看起来像下面。正如你可以看到我所需要的所有

IPersisting<ITransferable> 

情况,但问题是在retrieveData,使typeof运算(T)= ITransferable不给我足够的信息,以做反序列化。这就是为什么我将ITransferable的具体实践传递给构造函数(MyClass1,MyClass2)。这似乎工作,但感觉像一个黑客。

IPersisting<ITransferable> xfpMC1 = new XMLFilePersisting<ITransferable>("persistedMC1.xml", myTempDirectory, new MyClass1()); 
IPersisting<ITransferable> xfpMC2 = new XMLFilePersisting<ITransferable>("persistedMC2.xml", myTempDirectory, new MyClass2()); 

一个

+2

要改变的第一件事:从.NET命名约定开始。如果你满足他们的命名期望,它会让别人更容易阅读你的代码。 – 2015-02-07 07:56:00

+0

接下来,根本不清楚你会在哪里传递你想要的实际类型的信息。你的“当我创建一个XMLFilePersisting时,我使用的是接口,即ITransferable而不是实现类型,因为在我的客户端中我想把它们全部列在一起”对我来说没有多大的解释。你正在创建'XMLFilePersisting'的多个实例吗?如果是这样,为什么不为每个具体类型创建一个实例,然后从结果中创建一个大的'List '? – 2015-02-07 07:58:07

+0

对不起。我编辑了我的问题,以更好地显示我的调用代码中的相关部分 – 2015-02-07 08:34:22

回答

3

我建议你使每个XMLFilePersisting使用特定的具体类型,但随后的结果合并成一个List<ITransferable>。例如:

// Names changed to be more conventional 
var class1Loader = new XmlFilePersister<MyClass1>("MC1.xml", myTempDirectory"); 
var class2Loader = new XmlFilePersister<MyClass2>("MC2.xml", myTempDirectory"); 

// Could do all of this in one statement... note that this uses the 
// covariance of IEnumerable<T> 
IEnumerable<ITransferable> class1Results = class1Loader.RetrieveData(); 
IEnumerable<ITransferable> class2Results = class2Loader.RetrieveData(); 
var allResults = class1Results.Concat(class2Results).ToList(); 

已经误解了这个问题咯,如果它是你想在列表中,持久,你可以做XMLFilePersisting<T>实现IPersisting<ITransferable> - 虽然那么你有问题,当您尝试数据而不是读它......因为你需要从ITransferable投到T,这在执行时显然会失败。

基本上,我不知道你是否应该有两个接口:IDeserializer<out T>ISerializer<in T>。通过这些协变和反变化的接口,您可以轻松地获得一个不丢失信息或不需要执行时间检查的List<IDeserializer<ITransferable>>

+0

你有两个错误,当两次调用'class1Loader。RetrieveData();'和'class2Results'应该叫'class2Loader.RetrieveData();'? – Grundy 2015-02-07 09:41:13

+0

@Grundy:是的,修复。 – 2015-02-07 09:47:41

+0

不幸的是,我不认为这对我有用,因为我需要一个List >而不是List 。由于IPersisting是不变的(对吗?)我不能从'XMLFilePersisting '转换为'IPersisting '其他线程指向反射,但我宁愿留在我的'黑客'存储任意T引用。 – 2015-02-07 11:07:02

相关问题