如何在运行时决定传递哪种类型作为泛型参数?

4

我有几个特定的消息队列,并且在它们上面有特定的消息。我使用xsd.exe创建了这些消息的类。我可以使用以下方法同步接收消息并将其反序列化:

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

然后,我通过Fluent NHibernate持久化实体。

我有大约五个消息队列,每个队列都有自己的消息类型。 我希望保持这个小处理器应用程序的可维护性,以便添加更多的消息队列和消息类型不会变得困难。

因此,我在我的app.config中有一个队列名称列表,我使用它来在启动时创建消息队列,然后我想将一个方法连接到所有队列的.ReceiveCompleted事件:

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);
 }
}

但是当我尝试将entityType传递给泛型方法时,会出现"Type or namespace name expected"的错误。 我可能做了一些非常愚蠢的事情,但我无法弄清楚这应该如何工作。
我尝试使用dynamic关键字和.MakeGenericType,但没有成功。 我还看了以下内容:
- Dynamic Generic declaration of type T - Function returning a generic type whose value is known only at runtime - Determining a Generic Type at Runtime in Non-Generic Class - How to pass variable of type "Type" to generic parameter 但我仍然不明白...能帮忙吗?

所以我的问题要点是:我有一个需要传递泛型参数的方法。我想在运行时决定传递哪种类型到这个方法中。我该怎么做? - autonomatt
你应该解释一下你所说的“没有运气”的意思。这些问题的方法出了什么问题?你必须使用MakeGenericMethod函数。 - nawfal
可能是如何使用反射调用泛型方法?的重复问题。 - nawfal
2个回答

0

很遗憾,泛型并不适合像这样动态地运行。泛型参数必须在设计时定义。我已经有一段时间没有使用NHibernate了,但是难道没有一种类似于以下语法的方式来插入实体吗:

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

编辑:

或者

 Session.SaveOrUpdate(object);

我认为现在应该是类似于Session.SaveOrUpdate(object)的形式,我相信NHibernate不关心你发送的类型是什么,因为它会使用反射来确定正在保存的内容。 - F.B. ten Kate
好的,我进行了编辑以显示两者,因为他在上面使用了存储库模式,我认为这两个片段都可能有用。 - Steve Danner
谢谢。我正在努力让DeserializeMessage<T>(message)调用正常工作,而不是NHibernate的调用。 - autonomatt
那么,如果泛型参数必须在设计时定义,那我应该使用动态类型吗?还是应该使用对象类型,然后转换为我的某个类型? - autonomatt
我个人会将其返回类型设置为object,并像您在DeserializeMessage方法中已经做的那样显式转换它。也许您有一个基类或接口可以从该方法中返回? - Steve Danner
很遗憾,没有通用接口。这些类只是属性包。 真可惜,我以为泛型应该可以减轻装箱的问题。 - autonomatt

0

我不确定这是否回答了我的问题。我想做的就是:在运行时,如果x = 1,则调用myMethod<ClassA>(),如果x = 2,则调用myMethod<ClassB>()... - autonomatt
是的,我知道,基本上以下链接已经完成了所有的工作,我只是给了一些链接,希望你能弄清楚其余的部分 :)https://dev59.com/Z3VC5IYBdhLWcg3woCrN - F.B. ten Kate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接