有人可以帮我解决我在封闭代码中遇到的转换问题吗...我评论了代码行,我遇到了问题。这是否是实现这一目标的正确方法......我正在尝试做的是指定类型的前向响应以提供回调。
编辑1
我忘了提及Response和AFResponse是抽象类, 其中:>响应 - > 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无法保持所有的基类 回复消息?有没有办法实现这一点,或者我 我试着把头伸进墙里?
编辑3
现在我面临另一个问题......当消息到达时,它就是 由字节数组组成,&gt;进入解析的消息工厂 并构建它:
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(响应响应)事件处理程序 被调用,然后将消息转发给订阅者 消息,如果有的话。现在的问题是,如果我订阅(子层 响应是:AFResponse,SystemResponse等...) SystemResetResponse是SystemResponse的子类,它是 Response的子类,我必须从中转发响应 响应(基础)类型一直到具体类型,即 SystemResetResponse按顺序在MessageBinder中的Forwarder可以找到 此消息类型的订阅者,并转发它。
有许多类型和手工铸造将是一个矫枉过正的...是 有办法解决这个问题,甚至是设计这种类型的更好方法 系统
编辑4
我改变了这样的代码......这是正确的方法吗,是 还有其他,更好的方式,而且我还在努力解决问题 问题是正确的方法还是有更好的方法来解决这个问题?
private void OnAsyncResponseReceived(Response response)
{
dynamic resolvedResponse = Convert.ChangeType(response, response.GetType());
messageBinder.Forward(resolvedResponse);
}
答案 0 :(得分:2)
您需要将subscribers
列表中的每个项目投放到Subscriber<TResponse>
。
像这样的东西总是对我有用 -
private List<T> get<T>()
{
List<IEntity> list = new List<IEntity>();
List<T> genericList = new List<T>();
foreach (var item in list)
{
genericList.Add((T)item);
}
return genericList;
}
希望它有所帮助!!
答案 1 :(得分:2)
除了已提供的答案外,还有以下几行代码......
Type responseType = typeof (TResponse);
if (responseType.IsSubclassOf(typeof (AFResponse)))
可以替换为:
if (response is AFResponse)
或(更好)
AFResponse af = response as AFResponse;
if (af != null)
编辑更新了代码,因为我事先没有意识到TResponse是通用的。您是否也知道IsSubclassOf如果匹配类型会返回false?
答案 2 :(得分:2)
您的部分问题是您尝试将字典声明为具有通用订阅者(List<Subscriber<Response>>
),同时期望每个条目都是不相关的类型(List<Subscriber<TResponse>>
)。解决方案是隐藏object
或IList
:
private readonly Dictionary<Type, object> bindings;
private List<Subscriber<TResponse>> GetSubscribers<TResponse>()
where TResponse : Response
{
object subscribers;
bindings.TryGetValue(typeof(TResponse), out subscribers);
return (List<Subscriber<TResponse>>)subscribers;
}
您的Forward
方法可以更简单地检查AFResponse
和子类,但演员必须经过object
:
public void Forward<TResponse>(TResponse response)
where TResponse : Response
{
var subscribers = GetSubscribers<TResponse>();
if (subscribers != null)
{
Subscriber<TResponse> subscriber;
var afResponse = response as AFResponse;
if (afResponse != null)
{
subscriber = subscribers.SingleOrDefault(s => s.ShortAddress == afResponse.ShortAddress);
}
else
{
subscriber = subscribers.First();
}
if (subscriber != null)
{
subscriber.Forward(response);
}
}
}
的更新强> 的
您没有声明您的词典包含“所有邮件的基类”。尽管Response
是所有回复的基类,但Subscriber<Response>
和Subscriber<T>
是不相关的类型。这有点类似于List<int>
和List<string>
不相关的方式,即使string
和int
都来自object
。
您要查找的内容名为covariance,仅受某些界面支持。
例如,如果你有:
interface ISubscriber<out T> where T:Response
{}
class Subscriber<T> : ISubscriber<T> where T:Response
{}
你可以这样做:
ISubscriber<Response> s = new Subscriber<AFResponse>();
但是,List<ISubscriber<Response>>
和List<ISubscriber<AFResponse>>
仍然是不相关的类型。