views:

75

answers:

2

I have several message queues that have specific messages on them. I've created classes for these messages using xsd.exe. I can receive a message syncronously and deseriazlise it with this method:

public oneOfMyTypes DeserializeMessage(XDocument message)
{
 var serializer = new XmlSerializer(typeof(oneOfMyTypes));
 var entity = (oneOfMyTypes)serializer.Deserialize(message.CreateReader());
 return entity;
}

I then persist the entity via Fluent NHibernate.

So I've got about five message queues that all have their own type of message. I would like to keep this little processor app maintainable, so that adding more message queues and message types doesn't become a pain.

So I have a list of queue names in my app.config that I use to create the message queues on start up and then I want to wire up a single method to the .ReceiveCompleted event of all queues:

void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
 var queue = (MessageQueue)sender;
 var message = queue.EndReceive(e.AsyncResult);
 var body = message.Body.ToString();
 var xml = XDocument.Parse(body);
 var queueName = queue.QueueName;
 Type entityType = GetTypeFromQueueName(queueName);
 entityType entity = DeserializeMessage<entityType>(xml);

 var repository = new LogRepository();
 repository.AddEntity<entityType>(entity);
}

private T DeserializeMessage<T>(XDocument message)
{
 var serializer = new XmlSerializer(typeof(T));
 var entity = (T)serializer.Deserialize(message.CreateReader());
 return entity;
}

public Type GetTypeFromQueueName(string queueName)
{
 switch (queueName)
 {
  case "some-message-queue-name":
   return typeof (oneOfMyTypes);
 }
}

But when I try to pass entityType to the generic methods I get "Type or namespace name expected". I'm probably doing something really silly, but I can't figure out how this should work.

I've tried using the dynamic keyword and also .MakeGenericType but no luck. I've also looked at:

But I'm still not getting it ... help?

A: 

This link should help you

http://todotnet.com/post/2006/11/13/Instantiating-Generic-Types-at-runtime.aspx

You should be able to go from the link i posted to call the methode through reflection.

See the following link:

http://www.victorchen.info/call-static-method-with-a-string-name/

So basically when you've created your generic Type, you then grab the MethodInfo of your static method and then call the Invoke method on the MethodInfo object.

(i haven't actually tried this but in theory i believe it should work)

F.B. ten Kate
I'm not sure this answers my questions. All I want to do is this: Given myMethod<T>(), at runtime, if x = 1 then call myMethod<ClassA>() if x = 2 then call myMethod<ClassB>()...
mattRo55
Yes i know, basically the following link did all the legwork i didn't i simply gave a few links and hoped you'd figure out the rest :)http://stackoverflow.com/questions/232535/how-to-use-reflection-to-call-generic-method
F.B. ten Kate
+1  A: 

Unfortunately, generics are not meant to function dynamically like this. Generic parameters must be defined at design time. It's been a while since I've used NHibernate, but isn't there a way to insert entities with a syntax like:

repository.AddEntity(entity, typeof(myEntityType));

EDIT:

or

 Session.SaveOrUpdate(object);
Steve Danner
I believe atm it should something like Session.SaveOrUpdate(object) i believe NHibernate does not care what type your send in as it will use reflection to figure out what it is saving.
F.B. ten Kate
Good call, I edited to show both since he's using the repository pattern above, I think both snippets might be useful.
Steve Danner
Thanks. It's not so much the call to NHibernate, but rather the DeserializeMessage<T>(message) call that I'm trying to get working...
mattRo55
So if generic paramters must be defined at design time, then should I use a dynamic type? ... or should I just use a type of object and then cast to one of my types?
mattRo55
I personally would just have it return type object and cast it explicitly like you already do in the DeserializeMessage method. Maybe you've got a base class or interface you could return from that method instead?
Steve Danner
Unfortunately, there is no common interface. These classes are just property bags.Shame, I thought generics was supposed to alleviate boxing.
mattRo55