Reputation: 413
I have a lot of methods which return lists of data sets which are represented as the key (DateTime
) and value (some ValueType
or string
, I can't know it) pair, and this data sets may have size for about 10 000 items and more. For example:
public List<DataSet> GetAnyData(...)
{
var resultList = new List<DataSet>(); // Create the list for the base class
resultList.Add(new DoubleDataSet()); // This classes will be filled in this method
resultList.Add(new StringDataSet()); // See the description for them below
return resultList;
}
Example of the result list from this method:
ListItem1 ListItem2
Date1 Values1 Date2 Values2
01:00 10.5 02:00 "a"
01:15 20.42 02:15 "b"
01:30 30.01 02:30 "c"
After receiving this data sets I need to process them by different ways (using LINQ). And my problem is: how to create the DataSet class?
I tryed a lot of solutions:
1) To Inherit the DataSet class from Dictionary using generic types:
abstract class DataSet<T> : Dictionary<DateTime, T> {...}
and to create specific classes:
class DoubleDataSet : DataSet<double> {...}
class StringDataSet : DataSet<string> {...}
But the problem is: how to create the base class which I could store in the List of data sets?
2) Create the class of the DataItem
of the DataSet
and use it in the first solution:
class DataItem
{
public double DoubleValue { get; set; }
public string StringValue { get; set; }
// etc
}
class DataSet : Dictionary<DateTime, DataItem> {...}
But the problem is: how to know what property of the DataItem
I need to take?
3) Store data in the object
class:
public class DataSet : Dictionary<DateTime, object> {...}
public class DoubleDataSet : DataSet
{
public new double this[DateTime key]
{
get { return base[key] as double; }
set { base[key] = value; }
}
}
But the problem is: what about boxing and unboxing? If I will have 50 000 values and every value will be converted to object and back to the required type it will spent a lot of time. Also using LINQ the type of DataSet
value will be an object
and I will need to know what type is it.
4) Store the dictionary with the data inside the DataSet
class:
public class DataSet
{
public Dictionary<DateTime, DataItem> Items {get; set;}
}
public class DoubleDataSet : DataSet
{
public new Dictionary<DateTime, double> Items
{
get { return base.Items // It wouldn't work because there a new dictionary is created
.ToDictionary(q => q.Key, q => q.Value.DoubleValue); }
set { base.Items = value
.ToDictionary(q => q.Key, q => new DataItem(q.Value, null)); }
}
}
But the problem is: get { return base.Items.ToDictionary(q => q.Key, q => q.Value.DoubleValue); }
returns a new instance of the Items
dictionary and I can't modify the original list.
So help me please how to create the base class of the generic type dictionary to store it in a list?
I will be very grateful for any help! I know that there is an error of designing (or coding) and I will be glad if anyone will help me to find it! Is it even possible to solve this problem?
Upvotes: 1
Views: 857
Reputation: 622
If I understood you correctly, you need to store and process objects of different types in your list, but at the processing time, you don't know on which type of object you are working on.
One thing you could try: Since your DataItem
class knows what type it is, why don't you let it decide how it gets processed by it implementing the visitor pattern?
To implement this, you would have to do the following: First, implement your different data items:
// base class you can use in dictionaries
// note that is does not store any data type
class DataItem
{
// method called from outside
// for processing the item
public abstract void GetProcessed(Processor p);
}
// DataItem which stores a double
class DoubleDataItem : DataItem
{
public double Data{get;set;}
public override void GetProcessed(Processor p)
{
p.Process(this);
}
}
// DataItem which stores a string
class StringDataItem : DataItem
{
public string Data {get;set}
public override void GetProcessed(Processor p)
{
p.Process(this);
}
}
Now the information, which type of data is used is only stored in the relevant class. Every class can also retrieve a processor (or a visitor). This processor/visitor can then have different implementations depending on the type it is operating on:
public class Processor
{
// do processing for double items
public void Process(DoubleDataItem d);
// do processing for string items
public void Process(StringDataItem d);
}
Now when you create your dictionary, the processor will execute the correct code depending on which item it is operating on:
var dictionary = new Dictionary<DateTime,DataItem>();
// fill dictionary with data item
var processor = new DoSomethingProcessor();
foreach (var entry in dictionary)
entry.Value.GetProcessed(processor);
Upvotes: 2