誰かが私が直面している変換を同封のコードで手伝ってくれますか...私は問題を抱えているコードの行にコメントしました。これはこれを達成するための正しい方法です...私がやろうとしているのは、指定されたタイプの応答を提供されたコールバックに転送することです。
編集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などです...)ResponseのサブクラスであるSystemResponseのサブクラスであるSystemResetResponseをサブスクライブする場合、Response(base)タイプallからその応答をキャストする必要があることです。 MessageBinderのフォワーダーがこのメッセージタイプのサブスクライバーを見つけて転送するための具体的なタイプであるSystemResetResponseへの道。
多くのタイプがあり、手でキャストするのはやり過ぎでしょう...これを回避する方法、またはこのタイプのシステムを設計するためのより良い方法はありますか?
編集4
私はこのようなコードを変更しました...これはこれを行うための正しい方法ですか、他のより良い方法がありますか、そして全体として、私は問題を正しい方法で解決しようとしていますか、それともこれを処理するためのより良い方法がありますか?
private void OnAsyncResponseReceived(Response response)
{
dynamic resolvedResponse = Convert.ChangeType(response, response.GetType());
messageBinder.Forward(resolvedResponse);
}