【发布时间】:2019-04-14 10:30:32
【问题描述】:
我正在处理一个将 XML 消息发布到我的服务器的微信项目。该消息可以是多种类型中的任何一种。因此,我首先将消息反序列化为具有基本“WxMessage”的相应对象,然后将该对象返回给调度程序,调度程序将找出正确的消息处理程序来处理消息。对应于每种类型的消息的处理程序通过 IWxMessageHandler 接口注册到 Asp.net core 2.1 的 DependencyInjection。
services.AddScoped<IWxMessageHandler<WxMessage_Image>, WxMessageHandler_Image>();
services.AddScoped<IWxMessageHandler<WxMessage_Text>, WxMessageHandler_Text>();
services.AddScoped<IWxMessageHandler<WxMessage_File>, WxMessageHandler_File>();
这是消息服务:
public async Task<string> Handle(string messageBody)
{
var reply = default(WxMessage);
using (var deserial = new WxInMessageDeserializer())
{
var deserializedModel = deserial.Parse(messageBody);
reply = (WxReplyMessage_Text) await HandleMessage(deserializedModel);
}
return await Task.FromResult(BuildXmlContent(reply));
}
public async Task<WxMessage> HandleMessage<TMessage>(TMessage message)
{
var _handler = _serviceProvider.GetService<IWxMessageHandler<TMessage>>();
......
}
但是它未能解决 IWxMessageHandler 的正确实现,因为 WxInMessageDeserializer 返回了 WxMessage 的基础对象:
var result = default(WxMessage);
switch (_msgTYpe)
{
case "text": result = (WxMessage_Text)new XmlSerializer(typeof(WxMessage_Text))
.Deserialize(new StringReader(rawMessage));
break;
case "image": result = (WxMessage_Image)new XmlSerializer(typeof(WxMessage_Image))
.Deserialize(new StringReader(rawMessage));
break;
case "voice": result = (WxPushMessage_Voice)new XmlSerializer(typeof(WxPushMessage_Voice))
.Deserialize(new StringReader(rawMessage));
break;
......
case "file": result = (WxMessage_File)new XmlSerializer(typeof(WxMessage_File))
.Deserialize(new StringReader(rawMessage));
break;
}
return result;
我猜这是 C# 类型推断的限制,因为当我使用像 HandleMessage(somemessage) 这样的显式调用方法时结果是正确的。目前我正在通过旋转所有服务的列表来解决这个问题,然后选择我想要的:
var type = typeof(TMessage);
var _handler = _handlers
.Where(h => h.GetHandlingType().Equals(message.GetType()))
.FirstOrDefault();
var result = _handler.Handle(message);
return await result;
但我想知道是否有更好的解决方案来解决这个问题。 如果有人可以提供帮助,谢谢。
【问题讨论】:
-
不如将
IWxMessageHandlerFactory添加到services并将其注入到您的消息服务中?工厂可以将 TMessage 作为参数传递给Create()方法并返回正确类型的处理程序。
标签: c# generics asp.net-core dependency-injection type-inference