如何在运行时将基类转换为派生类。 我想要做的是以下几点:我需要一个系统,将持有的订阅, 某些类型的消息,有一个分配的订阅者。当收到一条消息时,它将被转发到这个系统,如果有这种消息的任何订阅者,它将进行查找,如果是的话,消息被转发给订阅者。我有一个叫做Response的抽象基类,接下来是一个抽象层,例如。 AFResponse:响应,然后有实际的(具体的)实现,例如。 回复(摘要):AFResponse(摘要):AFIncommingMessage(具体)。在运行时动态解析并将基类转换为派生类型
当接收到分组时,它前进到MessageBuilder,它解决了消息类型和建立的话,像这样:
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 ResolutionFailedException(str);
}
ConstructorInfo firstConstructor = resolvedType.GetConstructors().First();
return (T) firstConstructor.Invoke(new object[] {packet});
}
然后,如果消息被异步,它被转发到MessageBinder,持有订阅的消息类型。
private void OnAsyncResponseReceived(Response response)
{
messageBinder.Forward(response);
}
而一个MessageBinder类被实现为以下:
public class MessageBinder
{
private class Subscriber<T> : IEquatable<Subscriber<T>> where T : Response
{
...
}
private readonly Dictionary<Type, IEnumerable> bindings;
public MessageBinder()
{
this.bindings = new Dictionary<Type, IEnumerable>();
}
public void Bind<TResponse>(ushort shortAddress, Action<ZigbeeAsyncResponse<TResponse>> callback)
where TResponse : Response
{
HashSet<Subscriber<TResponse>> subscribers = this.GetSubscribers<TResponse>();
if (subscribers != null)
{
subscribers.Add(new Subscriber<TResponse>(shortAddress, callback));
}
else
{
var subscriber = new Subscriber<TResponse>(shortAddress, callback);
this.bindings.Add(typeof(TResponse), new HashSet<Subscriber<TResponse>> { subscriber });
}
}
public void Forward<TResponse>(TResponse response)
where TResponse : Response
{
var subscribers = this.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.FirstOrDefault();
}
if (subscriber != null)
{
Debug.WriteLine("Forwarding received async response of type " + response.GetType().Name);
subscriber.Forward(response);
}
}
}
private HashSet<Subscriber<TResponse>> GetSubscribers<TResponse>() where TResponse : Response
{
IEnumerable subscribers;
this.bindings.TryGetValue(typeof(TResponse), out subscribers);
return (HashSet<Subscriber<TResponse>>)subscribers;
}
}
,就会出现问题,当MessageBinder类的()的方法GetSubscribers被调用时,因为τ响应的类型是类型基类的,这是响应,因此没有找到用户。所以我认为我需要做的是以某种方式将实际类型的消息传递给Forward方法,以便该类型成为实际的响应类型。
我改变,像这样的方法:
private void OnAsyncResponseReceived(Response response)
{
messageBinder.Forward((dynamic)response);
}
它的工作,但不知何故,我的事情有一个更好的办法做到这一点?或者这是实际的和唯一的解决办法(?)?也许我应该改变整体设计,我不知道......我第一次面对这类问题,这就是我想出的。
我很乐意接受建议,评论家,当然,最好的解决方案:) 我很好奇,如果它不同于我的解决方案并且效率更高,那么您将如何实现此目标。 谢谢你的帮助!
从小孩投给父母很容易,但是父母对小孩是不可能的。例如,将文本框转换为控件是可能的,但对文本框的控制是不可能的。 – 2012-07-06 11:28:48
@NikhilAgrawal:你的意思是不可能投射到派生类? – 2012-07-06 11:43:23
隐含号码明确表示是。阅读本http://stackoverflow.com/questions/124336/a-way-of-casting-a-base-type-to-a-derived-type – 2012-07-06 11:48:35