Reputation: 67195
I have code similar to the following. It associates integers with types. I want to then use this dictionary to look up the type for an given integer, and then instantiate that type.
Dictionary<int, Type> RegistrationMethods;
RegistrationMethods = new Dictionary<int, Type>();
RegistrationMethods.Add(1, typeof(RegistrationProvider_01));
RegistrationMethods.Add(2, typeof(RegistrationProvider_02));
Question: All of my types implement IRegistrationMethod
. Is there any way to declare my dictionary so that it can only hold types that implement this interface? That would make my code more type safe.
Thanks for any tips.
Upvotes: 1
Views: 105
Reputation: 84745
You cannot enforce this restriction on a Type
, and therefore neither on a Dictionary<…, Type>
, but you could wrap such a dictionary in a specialized type:
class RestrictedTypeDictionary<TRestriction>
{
public RestrictedTypeDictionary()
{
this.internalDictionary = new Dictionary<int, Type>();
}
private readonly Dictionary<int, Type> internalDictionary;
public void Add(int key, Type value)
{
if (!typeof(TRestriction).IsAssignableFrom(value)) // <- that's the important bit
{
throw new ArgumentOutOfRangeException("value");
}
internalDictionary.Add(key, value);
}
public Type this[int key]
{
get
{
return internalDictionary[key];
}
}
…
}
You could then use a RestrictedTypeDictionary<IRegistrationMethod>
instead of a Dictionary<int, Type>
to ensure the constraint that only Type
values can be added that represent types deriving from IRegistrationMethod
.
Concerning your bonus, given any type T
with a default constructor, you can easily create an instance of that type using Activator.CreateInstance(typeof(T))
.
Upvotes: 1
Reputation: 101681
All of my types implement IRegistrationMethod. Is there any way to declear my dictionary so that it can only hold types that implement this interface? That would make my code more type safe.
You can create a wrapper class for your Dictionary
:
public class WrapperDictionary
{
private Dictionary<int, Type> dictionary;
public WrapperDictionary()
{
dictionary = new Dictionary<int, Type>();
}
public bool Add(int key, Type value)
{
if (!dictionary.ContainsKey(key) &&
value.IsAssignableFrom(typeof (IRegistrationMethod)))
{
dictionary.Add(key, value);
return true;
}
else return false;
}
public Type this[int key]
{
get
{
if (dictionary.ContainsKey(key)) return dictionary[key];
/* throw exception or return null */
}
}
}
In order to create an instance of given type, you can use Activator.CreateInstance
method:
var dict = new WrapperDictionary();
dict.Add(2, typeof(RegistrationProvider_01));
var type = dict[2];
var instance = Activator.CreateInstance(type);
Upvotes: 1
Reputation: 144136
If you just want to create them you could do:
Dictionary<int, Func<IRegistrationMethod>> RegistrationMethods;
RegistrationMethods.Add(1, () => new RegistrationProvider_01());
alternatively you could require all elements to be added through a method:
public void AddRegistrationMethod<T>(int i) where T : IRegistrationMethod, new()
{
RegistrationMethods.Add(i, typeof(T));
}
Upvotes: 6