Может кто-то помочь мне с преобразованием, с которым я столкнулся в прилагаемом коде ... Я прокомментировал строки кода, где у меня проблема. Это даже правильный способ достичь этого ... то, что я пытаюсь сделать, - это ответные реакции указанного типа на предоставленный обратный вызов.Преобразование родового типа в его базу и наоборот
EDIT 1
Я забыл упомянуть, что ответ и 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;
}
}
Благодарим за любую помощь :)
EDIT 2
Я изменил код в соответствии с @Bojan ответ, и он работает. Но Мне любопытно, почему Словарь не может содержать базовый класс всех Ответных сообщений? Есть ли способ сделать это, или я только пытался протащить голову через стену?
EDIT 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), обработчик события , который затем передает сообщение подписчику этого сообщения , если таковое имеется. Проблема заключается в том, что если я подписываюсь на (подслой ответа: AFResponse, SystemResponse и т. Д.) SystemResetResponse, который является подклассом SystemResponse, который является подклассом Response, который должен ответить на этот вопрос от Response (базовый) до бетонного типа, который составляет . SystemResetResponse для того, чтобы Экспедитор в MessageBinder мог найти подписчиков этого типа сообщения и пересылать его.
Есть много типов, и литье рук будет излишним ... Есть ли способ обойти это или даже лучший способ спроектировать этот тип системы ?
EDIT 4
Я изменил код, как это ... это правильный способ сделать это, это есть любой другой, лучший путь и над всем, я пытаюсь решить проблему правильный путь или есть лучший способ справиться с этим?
private void OnAsyncResponseReceived(Response response)
{
dynamic resolvedResponse = Convert.ChangeType(response, response.GetType());
messageBinder.Forward(resolvedResponse);
}
Благодарим вас за ответ! :) Но можете ли вы объяснить мне, почему словарь не может содержать базовый класс всех сообщений, поскольку Response является базовым классом всех ответов? – DavorinP
Я пробовал использовать ковариацию, но, как вы сказали, она не играет в моем случае или не делает этого? Теперь я столкнулся с другой проблемой ... как я могу отбросить ответ на конкретный тип durning runtime ... Я описываю проблему в редакции # 3. Спасибо! – DavorinP
Нет, ковариация не применяется в вашем случае. Что касается другой проблемы, я думаю, вам лучше разместить ее как другой вопрос. –