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
XMLFilePersisting? If so, why not create a single instance for each concrete type, then build a bigList<ITransferable>from the results?IPersisting<ITransferable>rather than anIPersisting<MyClass1>and anIPersisting<MyClass2>which would obviously solve the issue.