I have a Dictionary to map a certain type to a certain generic object for that type. For example:
typeof(LoginMessage) maps to MessageProcessor
You can't do that. You could try telling your problem from a more high level point of view (i.e. what exactly do you want to accomplish with the casted variable) for a different solution.
You could go with something like this:
public abstract class Message {
// ...
}
public class Message<T> : Message {
}
public abstract class MessageProcessor {
public abstract void ProcessMessage(Message msg);
}
public class SayMessageProcessor : MessageProcessor {
public override void ProcessMessage(Message msg) {
ProcessMessage((Message<Say>)msg);
}
public void ProcessMessage(Message<Say> msg) {
// do the actual processing
}
}
// Dispatcher logic:
Dictionary<Type, MessageProcessor> messageProcessors = {
{ typeof(Say), new SayMessageProcessor() },
{ typeof(string), new StringMessageProcessor() }
}; // properly initialized
messageProcessors[msg.GetType().GetGenericArguments()[0]].ProcessMessage(msg);
This is simply not allowed:
Type key = message.GetType();
MessageProcessor<key> processor = messageProcessors[key] as MessageProcessor<key>;
You cannot get a generic type as a variable value.
You'd have to do a switch or something:
Type key = message.GetType();
if (key == typeof(Foo))
{
MessageProcessor<Foo> processor = (MessageProcessor<Foo>)messageProcessors[key];
// Do stuff with processor
}
else if (key == typeof(Bar))
{
MessageProcessor<bar> processor = (MessageProcessor<Bar>)messageProcessors[key];
// Do stuff with processor
}
...
The answer of @DanielPlaisted before generally works, but the generic method must be public or one must use BindingFlags.NonPublic | BindingFlags.Instance
! Couldn't post it as a comment for lack of reputation.
As mentioned, you cannot cast it directly. One possible solution is to have those generic types inherit from a non-generic interface, in which case you can still invoke methods on it without reflection. Using reflection, you can pass the mapped object to any method expecting it, then the cast will be performed for you. So if you have a method called Accept expecting a MessageProcessor as a parameter, then you can find it and invoke it dynamically.
public delegate void MessageProcessor<T>(T msg) where T : IExternalizable;
virtual public void OnRecivedMessage(IExternalizable msg)
{
Type type = msg.GetType();
ArrayList list = processors.Get(type);
if (list != null)
{
object[] args = new object[]{msg};
for (int i = list.Count - 1; i >= 0; --i)
{
Delegate e = (Delegate)list[i];
e.Method.Invoke(e.Target, args);
}
}
}
The following seems to work as well, and it's a little bit shorter than the other answers:
T result = (T)Convert.ChangeType(otherTypeObject, typeof(T));