-1

インターフェイスを介して通信する複数のクラス間でメッセージをやり取りしようとしています。しかし、私はできるだけ一般的なものにしたいので、受信メッセージのメッセージ タイプが送信タイプと異なる可能性があるため、問題に遭遇しました。わかりやすくするためにいくつかのコードを貼り付けました。

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

インターフェイスの操作に関しては、私はまだかなり新鮮で、再帰、スタック オーバーフロー エラーなどに苦労しました。したがって、設計に関して改善できることや簡単な修正について提案がある場合は、私が学ぶのを手伝ってください. より良いパターンを実装する方法を理解したいと思っています。

ありがとう

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]
    }
}
4

1 に答える 1

1

ここであなたの目標を理解するのに苦労していますが、おそらくそうMessagePassing<U>(U message)あるべきです。MessagePassing(U message)interface IClientMessaginginterface IClientMessaging<U>

それから-しかし、なぜ が のサブスクライバーリストを実装および管理するのInProcessMessaging<T, U> : IClientMessaging<U>かわかりません。1 つのクラスがサブスクライバーを管理し、別のクラスがサブスクライバー ( ) であるように思えます。InProcessMessagingIClientMessagingIClientMessagingIClientMessaging

と言っUて、Tタイプが違います。まあ - それらは関連していますか?一方のラッパーは他方のラッパーですか?おそらくU、のラッパー、Tを含むTが追加情報を追加するジェネリッククラスのいずれかのように聞こえます。その場合、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)に、実装で whichを処理する前にそれobjectが であることを確認できます。TConsumed

それ以外の場合は、C# イベントを介してクライアントからクライアントへの直接リンクを作成できますが、中央のディスパッチャーを意図しているようです。リフレクションが必要になるか、渡された型を認識しないかのいずれかである、これらの異なる制限のない数の型を追跡する必要があるのは、中央のディスパッチャです (前の段落で説明したように)。

アイデアについては、 Reactive Extensionsと Observer パターンも参照する必要があります。

コメントが雑になりすぎたので削除しました。

于 2012-04-28T03:36:58.157 に答える