2012-04-28 16 views
0

私は、インターフェイス経由で通信するいくつかのクラス間でメッセージを渡そうとしています。しかし、私ができるだけジェネリックに行きたいので、着信メッセージのメッセージタイプが発信タイプと異なる可能性があるため、問題が発生しました。私はそれを明確にするためにいくつかのコードを貼り付けました。一般的なインターフェイスとタイプの解析

インターフェイスインプリメンテーションが着信メッセージを追加するはずのブロッキングコレクションのタイプと異なるタイプを渡すため、以下のコードはコンパイルされません。私は、着信タイプとは異なる可能性があるタイプを送信できるようにしたい(着信タイプは、常にブロッキングコレクションのエレメントのタイプと常に一致します)。インターフェイスやクラスを再設計する必要がある場合でも、何らかのキャストや解析を行うことができますか?

私はまだインターフェイスを使って作業することになり、再帰、スタックオーバーフローエラーなどで苦労しています。だから、もしあなたが私が賢明なデザインを改善したり、すぐに修正したりできるような提案があれば、私が学ぶのを助けてください。より良いパターンを実装する方法を理解することが非常に熱心です。

おかげ

public interface IClientMessaging 
{ 
    void MessagePassing<U>(U message); 
} 

public class InProcessMessaging<T> : IClientMessaging 
{ 
    private Dictionary<Type, List<IClientMessaging>> Subscriptions; 
    public BlockingCollection<T> MessageBuffer; 

    public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions) 
    { 
     //Setup Message Buffer 
     MessageBuffer = new BlockingCollection<T>(); 

     //Subscribe 
     Type type = typeof(T); 
     if (subscriptions.Keys.Contains(type)) 
     { 
      subscriptions[type].Add(this); 
     } 
     else 
     { 
      subscriptions.Add(type, new List<IClientMessaging>()); 
      subscriptions[type].Add(this); 
     } 

     Subscriptions = subscriptions; 
    } 

    public void SendMessage<U>(U message) 
    { 
     //Send message to each subscribed Client 
     List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)]; 
     foreach (IClientMessaging subscriber in typeSubscriptions) 
     { 
      subscriber.MessagePassing<U>(message); 
     } 
    } 

    public T ReceiveMessage() 
    { 
     return MessageBuffer.Take(); 
    } 

    public bool ReceiveMessage(out T item) 
    { 
     return MessageBuffer.TryTake(out item); 
    } 

    //Interface Implementation 
    public void MessagePassing<U>(U message) 
    { 
     MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want 
            //to send messages of a different type than the receiving type] 
    } 
} 
+1

なぜ 'InProcessMessaging'も' IClientMessaging'を実装し、 'IClientMessaging'のサブスクライバリストを管理していますか? –

答えて

1

は、私がここにあなたの目標を理解するために苦労してんだけど、おそらくMessagePassing<U>(U message)MessagePassing(U message)でなければならず、interface IClientMessaginginterface IClientMessaging<U>する必要があります。

InProcessMessaging<T, U> : IClientMessaging<U> - しかし、なぜわかりませんInProcessMessagingIClientMessagingを実装し、IClientMessagingのサブスクライバリストを管理しています。 1つのクラスが加入者を管理し、別のクラスが加入者であると私には思われます(IClientMessaging)。

UTは異なるタイプです。まあ、関係はありますか?もう一方のラッパーは1つですか?たぶんUのような音は、Tのラッパーか、Tを含む汎用クラスそのものですが、追加情報が追加されています。その場合には、コメントに基づいて

UPDATES

void MessagePassing<T>(Wrapper<T> message);これまで...

interface IClientMessage {} 

interface IClientMessage<U> : IClientMessage { /* ... */ } 

しかしにそれらの名前を変更:

interface IConsumer {} // (Or ISubscriber?) 

interface IConsumer<TConsumed> : IConsumer{ /* ... */ } 

をして追加します。

interface IGenerator { } 

interface IGenerator <TGenerated> : IGenerator { 
    event EventHandler<TGenerated> ItemGenerated; 
} 

次に、

class Manager 
{ 
    Dictionary<TConsumed, IConsumer> consumers = new ... 

    /* Code for attaching ItemGenerated event handlers to clients */ 
} 

class MyClient : IGenerator<string>, IConsumer<Foo>, IConsumer<Bar> 
{ 
    event IGenerator<string>.ItemGenerated ... 

    void IConsumer<Foo>.Consume(...) ... 

    void IConsumer<Bar>.Consume(...) ... 
} 

はい、これはIConsumer<TConsumed>.Consume()を呼び出すためにリフレクションを使用します。または、ジェネリックを省略し、タイプとしてobjectを使用することができます。さらに、IClientMessageにはConsume(object message)を含めることができます。この処理では、処理する前にobjectTConsumedであることを保証できます。

C#イベントを使用して直接クライアントからクライアントへのリンクを作成することはできますが、中央のディスパッチャを意識しているようです。中央のディスパッチャは、反射を必要とするか、または渡されるタイプに気付かない(これらのタイプが前の段落で説明されている)かどうかを追跡する必要があります(前の段落で説明したとおり)。アイデアのためのオブザーバーパターン。

私は自分のコメントを削除しました。

+0

私はあなたの考えが反射を回避しないと信じていますか?私は強力なタイピングに忠実な解決策を探していますが、あなたの答えがそれにどう対処しているか分かりません。私が間違っていれば私を修正してください。前述のように、メッセージをブロックコレクションに渡すことができるので、私はこれまでにインターフェイスを使用すると考えた唯一の理由は、特定のメッセージタイプを一致するブロッキングコレクションを実装したクライアントに渡すために、タイプ。いかなる状況下でも、私は強いタイピングをやめたい。 –

+1

いいえ、そうではありません。あなたは 'is'と' as'のどちらも好きでない限り。私は、「より良い」部分が反映を避けると思います。 –

+0

uosɐs、あなたとあなたのアイデアを取ってくれてありがとう。あなたのアイデアを考えて遊ぶ時間を費やしました。私は静的クラスに特定の型を保持しているコレクションをブロックするリポジトリをセットアップして直接アクセスすることができると信じています。同じコレクションに同時に複数のクライアントを追加することは決してなく、1つの特定のブロッキングコレクションから複数のクライアントを消費することはありません。あなたのソリューションはエレガントに見えますが、異なるタイプのコレクションに対処したいという単純な問題を解決するために、同時に複雑すぎるようです。 –

関連する問題