I have an (existing) typed class of items:
Items<T>
T Value { get; }
T can be double, string or int.
I then have a class that has to hold several instances of Items. Within a single instance of this class, T is always the same. As it stands, the type actually contained is determined by a property and the container is not typed:
Data
DataType { get; set; }
Items<double>
double Value;
Items<string>
// ... and so on. Nasty stuff.
Ideally, of course, this would be
Data<T>
Items<T>
T value
Data instances are created from scratch in code, and can be loaded from a database. So of course a factory would be in our future, but what is the return type of the Create method?
Even worse, I need this:
DataCollection
// HERE'S THE PAIN: What's the type here?
List of Data<> instances with differing types
foreach (? data in someDataCollection)
if (thetypeof data is double)
doSomething();
else
doSomethingElse();
Now, I can solve this, but I can’t see a CLEAN way to solve this.
My first issue is the declaration of DataCollection. What is the type of the list? List<object>, so it can hold Data<double> and Data<string>?
There actually is a clean way to solve this; you can use a Dictionary with keys of the data type and values which are of type generic Func<> . You then pass the type to your create method, which then looks up the Func<> to use in the Dictionary based on the type, and invokes that Func<> to create or process your object.
Since I am working from pseudo code, basically it would look something like the below; you can play with it and modify it to get it to serve your needs, but this is the basic idea.
First, create a parent class for all data objects; note that this class has a lookup dictionary for functions to invoke on various types, and note that it is abstract:
Now subclass Data with a generic type that can be instantiated:
You can then create a DataCollection class using the parent type. Note the ProcessData() method; all it does now is loop over the elements and call Process() on each one:
…and you’re all set! Now you can invoke your DataCollection with different types of Data: