I am dealing with a WeChat project that post XML message to my server. The message could be any one of several types. Hence I first deserialize the message to corresponding object with a base "WxMessage", and then return the object to a dispatcher, which will find out a correct message handler to handle the message. The handlers, corresponding to each type of messages, were registered to the DependencyInjection of Asp.net core 2.1 with a IWxMessageHandler<> interface.
services.AddScoped<IWxMessageHandler<WxMessage_Image>, WxMessageHandler_Image>();
services.AddScoped<IWxMessageHandler<WxMessage_Text>, WxMessageHandler_Text>();
services.AddScoped<IWxMessageHandler<WxMessage_File>, WxMessageHandler_File>();
This is the message service:
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>>();
......
}
However it failed to resolve the correct implement of IWxMessageHandler<> as the WxInMessageDeserializer return a base object of 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;
I guess this is a limitation of the C# Type Inferencing, as the result was correct when I use explicit calling method like HandleMessage(somemessage). Currently I am solving this issue by revolving a list of all services and then select the one I want:
var type = typeof(TMessage);
var _handler = _handlers
.Where(h => h.GetHandlingType().Equals(message.GetType()))
.FirstOrDefault();
var result = _handler.Handle(message);
return await result;
Yet I am wondering if there is any better solutions to this issue. Thanks if anyone can help.