What I'm trying to do is for my game I'm developing I've got a messaging system that uses a telegram struct as follows:
public struct Telegram
{
private int sender;
private int receiver;
public int Receiver
{
get
{ return receiver; }
}
//Message of an enumerated messageToSend in Messages
private Message messageToSend;
public Message MessageToSend
{
get
{ return messageToSend; }
}
//for delayed messages
private double dispatchTime;
public double DispatchTime
{
get
{ return dispatchTime; }
set
{ dispatchTime = value; }
}
//for any additional info
private object extraInfo;
public object ExtraInfo
{
get
{ return extraInfo; }
}
public Telegram(double time, int otherSender, int otherReceiver,
Message otherMessage, object info = null)
{
dispatchTime = time;
sender = otherSender;
receiver = otherReceiver;
messageToSend = otherMessage;
extraInfo = info;
}
}
What I want to be able to do is since the extra info is something that is passed based on the message type and needs to be object, for convenience of not having to code a bunch of functions with various extra info types, I want to get the type of the object that its boxed to when the function gets passed the extra info variable.
I know that I can do that with .getType()
and store it in a Type
variable.
Here comes the tricky part that I'm not sure if I can do. What I want to do is then use that Type
variable to cast the object when the thing that received the telegram handles it based on the message type sent. Is that possible to do?
Can't use generic for the telegram class as it causes things to break when I just tried to convert my messaging code. Here is the rest of the relevant code:
/*Telegrams are stored in a priority queue. Therefore the < and ==
operators are overloaded so the PQ can sort the telegrams
by time priority. Times must be smaller than
SmallestDelay before two Telegrams are considered unique.*/
public const double SmallestDelay = 0.25;
public static bool operator ==(Telegram t1, Telegram t2)
{
return (Math.Abs(t1.dispatchTime - t2.dispatchTime) < SmallestDelay) &&
(t1.sender == t2.sender) &&
(t1.receiver == t2.receiver) &&
(t1.messageToSend == t2.messageToSend);
}
public static bool operator !=(Telegram t1, Telegram t2)
{
return (Math.Abs(t1.dispatchTime - t2.dispatchTime) > SmallestDelay) &&
(t1.sender != t2.sender) &&
(t1.receiver != t2.receiver) &&
(t1.messageToSend != t2.messageToSend);
}
public static bool operator <(Telegram t1, Telegram t2)
{
if (t1 == t2)
return false;
else
return (t1.dispatchTime < t2.dispatchTime);
}
public static bool operator >(Telegram t1, Telegram t2)
{
if (t1 == t2)
return false;
else
return (t1.dispatchTime > t2.dispatchTime);
}
sealed class MessageDispatcher
{
public const double sendMessageImmediately = 0.0;
public const int noAdditionalInfo = 0;
public const int senderIdIrrelevant = -1;
//a set is used as the container for the delayed messages
//because of the benefit of automatic sorting and avoidance
//of duplicates. Messages are sorted by their dispatch time.
private static SortedSet<Telegram> priorityQueue = new SortedSet<Telegram>();
/// <summary>
/// this method is utilized by DispatchMessage or DispatchDelayedMessages.
/// This method calls the messageToSend handling member function of the receiving
/// entity, receiver, with the newly created telegram
/// </summary>
/// <param name="receiver"></param>
/// <param name="messageToSend"></param>
private static void Discharge(ref BaseEntityInfo receiver, ref Telegram message)
{
if (!receiver.HandleMessage(ref message))
{
//telegram could not be handled
}
}
private MessageDispatcher() { }
public static readonly MessageDispatcher instance = new MessageDispatcher();
/// <summary>
/// given a messageToSend, a receiver, a sender and any time delay, this function
/// routes the messageToSend to the correct entity (if no delay) or stores it
/// in the messageToSend queue to be dispatched at the correct time. Entities referenced
/// by iD.
/// </summary>
/// <param name="delay"></param>
/// <param name="sender"></param>
/// <param name="otherReceiver"></param>
/// <param name="messageToSend"></param>
/// <param name="additionalInfo"></param>
public static void DispatchMessage(double delay, int sender,
int otherReceiver, Message message,
object additionalInfo = null)
{
//get the reciever
BaseEntityInfo receiver = EntityMgr.entityManager.GetEntityFromID(otherReceiver);
//make sure the Receiver is valid
if (receiver == null)
return;
//create the telegram
Telegram telegram = new Telegram(0, sender, otherReceiver, message, additionalInfo);
//if there is no delay, route telegram immediately
if (delay <= 0.0)
//send the telegram to the recipient
Discharge(ref receiver, ref telegram);
//else calculate the time when the telegram should be dispatched
else
{
double CurrentTime = Clock.Current();
telegram.DispatchTime = CurrentTime + delay;
//and put it in the queue
priorityQueue.Add(telegram);
}
}
/// <summary>
/// This function dispatches any telegrams with a timestamp that has
/// expired. Any dispatched telegrams are removed from the queue as it
/// sends out any delayed messages. This method is called each time through
/// the main game loop.
/// </summary>
public static void DispatchDelayedMessages()
{
double CurrentTime = Clock.Current();
//now peek at the queue to see if any telegrams need dispatching.
//remove all telegrams from the front of the queue that have gone
//past their sell by date
while (!(priorityQueue.Count == 0) &&
(priorityQueue.ElementAt(0).DispatchTime < CurrentTime) &&
(priorityQueue.ElementAt(0).DispatchTime > 0))
{
//read the telegram from the front of the queue
Telegram telegram = priorityQueue.ElementAt(0);
//find the recipient
BaseEntityInfo receiver = EntityMgr.entityManager.GetEntityFromID(telegram.Receiver);
//send the telegram to the recipient
Discharge(ref receiver, ref telegram);
//remove it from the queue
priorityQueue.Remove(priorityQueue.ElementAt(0));
}
}
}