有人可以帮助我解决我在封闭代码中面临的转换......我评论了我遇到问题的代码行。这甚至是实现这一目标的正确方法吗……我想做的是将指定类型的响应转发到提供的回调。
编辑 1
我忘了提到 Response 和 AFResponse 是抽象类,它们是:>Response -> AFResponse -> AF 层消息的具体实现
public class MessageBinder
{
private class Subscriber<T> : IEquatable<Subscriber<T>> where T : Response
{
...
}
private readonly Dictionary<Type, List<Subscriber<Response>>> bindings;
public MessageBinder()
{
this.bindings = new Dictionary<Type, List<Subscriber<Response>>>();
}
public void Bind<TResponse>(short shortAddress, Action<ZigbeeAsyncResponse<TResponse>> callback)
where TResponse : Response
{
List<Subscriber<TResponse>> subscribers = this.GetSubscribers<TResponse>();
if (subscribers != null)
{
subscribers.Add(new Subscriber<TResponse>(shortAddress, callback));
}
else
{
var subscriber = new Subscriber<TResponse>(shortAddress, callback);
// ERROR: cannot convert from 'List<Subscriber<TResponse>>' to 'List<Subscriber<Response>>' ... tried LINQ Cast operator - does not work either
this.bindings.Add(typeof(TResponse), new List<Subscriber<TResponse>> { subscriber });
}
}
public void Forward<TResponse>(TResponse response)
where TResponse : Response
{
var subscribers = this.GetSubscribers<TResponse>();
if (subscribers != null)
{
Subscriber<TResponse> subscriber;
Type responseType = typeof (TResponse);
if (responseType.IsSubclassOf(typeof (AFResponse)))
{
// ERROR: Cannot convert type 'TResponse' to 'AFResponse' ... tried cast to object first, works, but is this the right way?
var afResponse = (AFResponse)response;
subscriber = subscribers.SingleOrDefault(s => s.ShortAddress == afResponse.ShortAddress);
}
else
{
subscriber = subscribers.First();
}
if (subscriber != null)
{
subscriber.Forward(response);
}
}
}
private List<Subscriber<TResponse>> GetSubscribers<TResponse>() where TResponse : Response
{
List<Subscriber<Response>> subscribers;
this.bindings.TryGetValue(typeof(TResponse), out subscribers);
// ERROR: How can I cast List<Subscriber<Response>> to List<Subscriber<TResponse>>?
return subscribers;
}
}
感谢您的任何帮助 :)
编辑 2
我根据@Bojan 的回答更改了代码,它正在工作。但我很好奇,为什么 Dictionary 不能容纳所有 Response 消息的基类?有没有办法做到这一点,或者我只是想把头推过墙?
编辑 3
现在我面临另一个问题......当消息到达时,它由字节数组组成,>它进入解决并构建它的消息工厂:
public static T Build<T>(Packet packet) where T : Response
{
Type resolvedType;
if (!dependencyMap.TryGetValue(packet.MessageId, out resolvedType))
{
var str = String.Format("Could not resolve message. Message info: CMD0: {0}, CMD1: {1}, MessageID: {2}",
packet.Cmd0, packet.Cmd1, packet.MessageId);
Debug.WriteLine(str);
throw new MessageNotFoundException(str);
}
ConstructorInfo firstConstructor = resolvedType.GetConstructors().First();
return (T) firstConstructor.Invoke(new object[] {packet});
}
然后调用OnAsyncResponseReceived(Response response)事件处理程序,然后将消息转发给该消息的订阅者(如果有)。现在的问题是,如果我订阅(响应的子层是:AFResponse、SystemResponse 等...) SystemResetResponse 是 SystemResponse 的子类,它是 Response 的子类,我必须从 Response(base) 类型中转换该响应具体类型 SystemResetResponse 的方式是为了让 MessageBinder 中的 Forwarder 可以找到该消息类型的订阅者,并转发它。
有很多类型,手动铸造会有点过分……有没有办法解决这个问题,或者甚至是更好的方法来设计这种类型的系统?
编辑 4
我更改了这样的代码......这是正确的方法吗?还有其他更好的方法吗?总的来说,我是在尝试以正确的方式解决问题还是有更好的方法来处理这个问题?
private void OnAsyncResponseReceived(Response response)
{
dynamic resolvedResponse = Convert.ChangeType(response, response.GetType());
messageBinder.Forward(resolvedResponse);
}