请有人帮我解决我在下面的代码中遇到的转换问题...我已经注释了代码中的那些行,我在这里遇到了问题。这是实现这个功能的正确方式吗...我试图做的是将指定类型的响应转发到提供的回调函数。
编辑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的答案改变了代码,它正在工作。但是,为什么字典不能持有所有响应消息的基类?有没有方法可以实现这一点,或者我只是试图让自己的头撞在墙上?
编辑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(基础)类型一直转换到具体类型,即 SystemResetResponse,以便 MessageBinder 中的 Forwarder 可以找到这个消息类型的订阅者并将其转发。
有很多类型,手动转换会过度繁琐...是否有其他方法解决这个问题,或者设计这种类型系统的更好方法?
编辑4:
我像这样更改了代码...这是正确的做法吗?是否有其他更好的方法,总之,我是在尝试以正确的方式解决问题,还是有更好的处理方式?
private void OnAsyncResponseReceived(Response response)
{
dynamic resolvedResponse = Convert.ChangeType(response, response.GetType());
messageBinder.Forward(resolvedResponse);
}