获取运行时间的最佳方式T的类型? [英] Best way to get runtime Type of T?
问题描述
列表与LT; XMLFilePersisting< ITransferable>>所有;
所以如果在retrieveData中我做typeof(T)应该返回ITransferable, info从文件加载项目。我可以想出如何做到这一点的唯一方法是通过在构造函数中传递ITransferable的实现者实例,但是这种感觉应该有更好的方式。建议?
公共界面IPersisting< T> {
列表< T> retrieveData();
bool persistData(List< T> lst);
}
public interface ITransferable {
类型getRuntimeType();
}
公共类XMLFilePersisting< T> :IPersisting< T> T:ITransferable {
private只读T defaultT;
// ...
public XMLFilePersisting(string thefile,string thepath,T def){
// ...
defaultT = def;
}
...
public List< T> retrieveData(){
List< T> retVal =新列表< T>();
类型runType = defaultT.getRuntimeType();
字符串elemName = runType.Name;
using(FileStream fs = new FileStream(FQ_FILE_PATH,FileMode.Open,FileAccess.Read)){
using(XmlReader reader = XmlReader.Create(fs)){
// below line won不工作,typeof在compileTime
解析// XmlSerializer xmlSer = new XmlSerializer(typeof(T));
XmlSerializer xmlSer = new XmlSerializer(runType);
if(reader.ReadToFollowing(elemName)){//跳转到第一个测试,跳过ListofT
do {
T testVal =(T)xmlSer.Deserialize(reader);
retVal.Add(testVal);
}
while(reader.ReadToNextSibling(elemName));
}
} // end using xmlreader
} //使用FileStream结束
return retVal;
} // end retrieveData
} //结束类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());
A
我建议你让每个> XMLFilePersisting
使用特定的具体类型,然后将结果合并到 List< ITransferable>
。例如:
//名称更改为更常规
var class1Loader = new XmlFilePersister< MyClass1>(MC1 .xml,myTempDirectory);
var class2Loader = new XmlFilePersister< MyClass2>(MC2.xml,myTempDirectory);
//可以在一个语句中完成所有操作......注意,这使用IEnumerable< T>的
//协方差。
IEnumerable< ITransferable> class1Results = class1Loader.RetrieveData();
IEnumerable< ITransferable> class2Results = class2Loader.RetrieveData();
var allResults = class1Results.Concat(class2Results).ToList();
误解了这个问题,如果是 persisters ,您希望成为在列表中,您可以使 XMLFilePersisting< T>
实现 IPersisting< ITransferable>
当您尝试存储数据而不是读取数据时...因为您需要从 ITransferable
转换为
基本上,我不知道你是否应该有两个接口: IDeserializer< ; out T>
和 ISerializer< in T>
。使用这些协变和反变化的接口,您可以轻松地在不丢失信息或不需要执行时间检查的情况下拥有 List< IDeserializer< ITransferable>>
。 b
Given the example code below, I'd like to get the runtime type of T inside a generic method (in this case retrieveData). When I create an XMLFilePersisting I use the interface, namely ITransferable rather than the implementing Types since in my client I want to have a list of all of them together:
List<XMLFilePersisting<ITransferable>> allThem;
So if in retrieveData I do typeof(T) that should return ITransferable which doesn't give me enough info to load the items from the file. The only way I could figure out how to do this was by passing an instance of the implementor of ITransferable in the constructor, but this kind of feels like there should be a better way. Suggestions?
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
Additional info:
Client code looks like below. As you can see I need all
IPersisting<ITransferable>
instances, but the problem is in retrieveData, that makes typeof(T) = ITransferable which doesn't give me enough info to do the deserialization. That is why I pass concrete implmentations of ITransferable to the constructor (MyClass1, MyClass2). This seems to work, but feels like a hack.
IPersisting<ITransferable> xfpMC1 = new XMLFilePersisting<ITransferable>("persistedMC1.xml", myTempDirectory, new MyClass1());
IPersisting<ITransferable> xfpMC2 = new XMLFilePersisting<ITransferable>("persistedMC2.xml", myTempDirectory, new MyClass2());
A
I would suggest that you make each XMLFilePersisting
use the specific concrete type, but then combine the results into a List<ITransferable>
. For example:
// 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();
Having misunderstood the question slightly, if it's the persisters you want to be in a list, you could make XMLFilePersisting<T>
implement IPersisting<ITransferable>
- although then you'd have problems when you try to store the data instead of reading it... because you'd need to cast from ITransferable
to T
, which could obviously fail at execution time.
Fundamentally, I wonder whether you should have two interfaces: IDeserializer<out T>
and ISerializer<in T>
. With those covariant and contravariant interfaces, you could easily have a List<IDeserializer<ITransferable>>
without losing information or needing execution-time checking.
这篇关于获取运行时间的最佳方式T的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!