3

How can I create a dictionary to store, as value, type that inherits another class?

For example:

Dictionary<String, typeof(Parent)> dict = new Dictionary<string, typeof(Parent)>();
dict["key1"] = typeof(Child1);
dict["key2"] = typeof(Child2);
dict["key3"] = typeof(Child3);

public abstract class Parent { }

public class Child1 : Parent { }
public class Child2 : Parent { }
public class Child3 : Parent { }

I do not want to store the instance but the class type.

EDIT: Sorry for my bad explanations of what I exactly want to do. I'm looking for a way to store the Type and make sure that this Type inherits Parent. I want to be type-safe and make sure that the store type is a child of Parent. The only way, for now, I figured how to do this is create my own implementation of IDictionary as here. But that's not what exactly I want. I would like to do this

Dictionary<string, typeof(Parent)> dict = ...

Any idea?

Community
  • 1
  • 1
Jeep87c
  • 1,050
  • 16
  • 36
  • You want `typeof` as in `dict["key1"] = typeof(Child1);` If you need to do this at runtime with an instance you would get the same value with `instance.GetType()` – asawyer Jun 20 '13 at 17:27
  • It's also worth noting that a dictionary of types is often the start of an IoC container. If you find yourself wanting object lifecycle management capabilities, it might be worth looking at one like Autofac or Ninject. – neontapir Jun 20 '13 at 17:43

4 Answers4

7

I think you just want to use Dictionary<string, Type> then when you add something you should do;

dict.Add("key1", typeof(Child1));

EDIT: As noted in Avi's answer you can use the GetType() method on an instance if you want to add a Type at runtime. If you're doing it at compile time, you generally will use typeof on the class.

Avi Turner
  • 10,234
  • 7
  • 48
  • 75
evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • That will work but, how can I ensure that the added value is a Child of Parent? I would like to be type-safe. – Jeep87c Jun 20 '13 at 17:58
  • @Jeep87c you can't do it in one simple statement. You could create a wrapper class because generic type constraints are specified at the class level. For example; if you are implementing a generic collection you could do `public class MyGenericList where T : Parent`. Or you could add an extension method which enforces type constraints prior to calling add. – evanmcdonnal Jun 20 '13 at 18:04
  • That's what I though... Thank you for your answer I will look through the potential solution using a wrapper. – Jeep87c Jun 20 '13 at 18:11
  • @Jeep87c overriding the `Add` method might be another option though I haven't tried it and don't know if it's allowed. Also, it could have negative side effects elsewhere (like for dictionaries that don't have these same type restrictions). Writing an extension method would be very clean, you just check that the type is a child of parent, if not throw and invalid argument exception otherwise call the normal add. However, that wouldn't prevent other dev's from using the normal add method to put types you don't want in the collection. – evanmcdonnal Jun 20 '13 at 18:17
2

Use typeof:

dict["key1"] = typeof(Child1);

or if you have an instance:

dict["key1"] = instance.GetType();
Avi Turner
  • 10,234
  • 7
  • 48
  • 75
1

To resolve your problem, you need to check via System.Reflection if your type inherits from Parent class. Check this answer for more information (link).

if (typeof(Parent).IsAssignableFrom(typeof(Child1)))
{
    dict["key1"] = typeof(Child1);
}

or this one (link)

int n = 0;
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
foreach (Type type in types)
{
    if (type.IsSubclassOf(typeof(Parent)))
    {
         dict["key" + n] = type;
         n++;
    }
}

EDIT:

To provide alternate solution...

var result = System.Reflection.Assembly.GetExecutingAssembly()
            .GetTypes()
            .Where(t => t.IsSubclassOf(typeof(Parent));

foreach(Type type in result)
{
    dict["key" + n] = type;
    n++;
}

I think there is no 'direct' solution to this problem.

Community
  • 1
  • 1
HuorSwords
  • 2,225
  • 1
  • 21
  • 34
  • I think this is really close to what I want. Is there any way to avoid the if and/or the foreach statement? For example, throw an exemption if somebody try to do this dict["key1"] = typeof(SomethingElse); where SomethingElse is not a child of class Parent. – Jeep87c Jun 20 '13 at 18:01
0
var dict = new Dictionary<String, Type>;
dict["key1"] = typeof(Child1);
John Fisher
  • 22,355
  • 2
  • 39
  • 64