Reputation: 4125
I have several dictionaries:
Dictionary<int, Type1> Type1Dictionary { get; set; }
Dictionary<int, Type2> Type2Dictionary { get; set; }
Dictionary<int, Type3> Type3Dictionary { get; set; }
Dictionary<int, Type4> Type4Dictionary { get; set; }
Where Typei (i = 1..4)
are derived from the same base class (BaseType
). I want a method that returns the reference of a dictionary given a type. Later, I will perform some operations like Add or Remove on that dictionary:
Type1 example = new Type1();
var dic = GetDictionary(example);
dic.Add(example.ID, example);
Notes: I don't want to set my dictionaries as Dictionary<int, BaseType>
I could write something like this but that wouldn't return a reference to the dictionary:
Dictionary<int, BaseType> GetDictionary(BaseType myObject)
{
var dic = new Dictionary<int, BaseType>();
if(myObject is Type1)
{
//ideally I would return my Type1Dictionary here but I can't due type incompatibility
foreach(var x in Type1Dictionary)
{
dic.Add(x.Key, x.Value);
}
return dic;
}
if(myObject is Type2) { /*...*/ }
if(myObject is Type3) { /*...*/ }
if(myObject is Type4) { /*...*/ }
}
EDIT:
What I really want is to avoid the following structure:
AddObject(BaseType x)
{
Type1 x1 = x as Type1;
if(x1 != null) { Type1Dictionary.Add(x1.ID, x1); }
Type2 x2 = x as Type2;
if(x2 != null) { Type2Dictionary.Add(x2.ID, x2); }
Type3 x3 = x as Type3;
if(x3 != null) { Type3Dictionary.Add(x3.ID, x3); }
Type4 x4 = x as Type4;
if(x4 != null) { Type4Dictionary.Add(x4.ID, x4); }
}
RemoveObject(BaseType x)
{
Type1 x1 = x as Type1;
if(x1 != null) { Type1Dictionary.Remove(x1.ID); }
Type2 x2 = x as Type2;
if(x2 != null) { Type2Dictionary.Remove(x2.ID); }
Type3 x3 = x as Type3;
if(x3 != null) { Type3Dictionary.Remove(x3.ID); }
Type4 x4 = x as Type4;
if(x4 != null) { Type4Dictionary.Remove(x4.ID); }
}
But instead:
AddObject(BaseType x)
{
var dic = GetDictionary(x);
dic.Add(x.ID, x);
}
RemoveObject(BaseType x)
{
var dic = GetDictionary(x);
dic.Remove(x.ID);
}
Upvotes: 7
Views: 89
Reputation: 64487
The DLR can play these tricks: dynamic dispatch. It resolves the required method at runtime. This allows you to have many dictionaries of strong types, but a more generalised handling mechanism. I do this for handling events that come from a common event base.
class Program
{
private static Dictionary<int, Foo> _foos = new Dictionary<int, Foo>();
private static Dictionary<int, Baz> _bazs = new Dictionary<int, Baz>();
static void Main(string[] args)
{
Bar foo = new Foo();
Bar baz = new Baz();
Add(foo); // Resolves at runtime to Add(Foo f)
Add(baz); // Resolves at runtime to Add(Baz b)
}
public static void Add(Bar b)
{
Add((dynamic)b);
}
private static void Add(Foo f)
{
_foos.Add(1, f);
}
private static void Add(Baz b)
{
_bazs.Add(1, b);
}
}
class Foo : Bar
{
}
class Baz : Bar
{
}
class Bar
{
}
Moving stuff into the DLR comes with its own pitfalls (namely what were compile-time problems are now runtime problems), so this needs reviewing. It is just one approach. Another approach is an implementation of the visitor pattern. Another approach is what you've currently got.
Don't take this answer as the way to do it.
Upvotes: 0
Reputation: 22064
This can be polished in the terms of thead safety, etc. But you should be able to get the basic idea:
public interface IEntity
{
int ID { get; }
}
public class Superset<T> where T : IEntity
{
public Dictionary<Type, Dictionary<int, T>> m_Map =
new Dictionary<Type, Dictionary<int, T>>();
private Dictionary<int, T> GetDictionary(Type t)
{
Dictionary<int, T> result = null;
if (!m_Map.TryGetValue(t, out result))
{
result = new Dictionary<int, T>();
m_Map.Add(t, result);
}
return result;
}
public void Add<K>(K item) where K : T
{
GetDictionary(typeof(K)).Add(item.ID, item);
}
public bool Remove<K>(K item) where K : T
{
return GetDictionary(typeof(K)).Remove(item.ID);
}
}
Upvotes: 5