1

TCP 接続ベースの DLL を作成しています。
基本的な前提は、どのクライアントでも使用でき、クライアントが行う必要があるのは、IP アドレスとポート番号を指定することだけであり、その後、dll が接続、メッセージの送信、切断の検出などを処理します。dll は 3 つのイベントConnectedを公開します。クライアントはこれらに接続するだけで使用できますDisconnectedMessageReceivedDLL は、クライアントが継承できる基本クラスも定義し、Message送受信のために独自のクラス/オブジェクトを DLL に渡します。

dll で、Packetクラスとサポートする型を定義しました。

[Serializable]
internal class Packet
{
    private MessageType _type;
    private MessageItem _item;

    public MessageType MYtpe
    {
        get
        {
             return _type;
        }
        set
        {
            _type = value;
        }
    }

     //similar for MessageItem
     // ...
}

列挙型:

public enum MessageType
{
    None,
    PollItem,
    Binary1,
    Binary2
}

オブジェクト/クラス送信の基本クラス:

public abstract class MessageItem
{
}

私の低レベル、DLLに隠されているクラス、コードを送信すると、これになります(エラー処理なし)

internal bool SendPacket(Packet p)
{
    bool sentOk = false;
    BinaryFormatter bin = new BinaryFormatter();
    try
    {
         bin.Serialize(theNetworkStream, p);
    }
    catch etc..
}

ReadPacketは基本的にその逆です。

dll は、パケットを構築し、上記の送信関数を呼び出す、クライアントが使用する関数を公開します。

public void SendMessage(MessageType type, MessageItem message)

今、クライアントのために。DLL で 2 つのバイナリ列挙型を定義したので、クライアント コードで 2 つの別個のクラスを使用できます。

例えば

public class Employee : MessageItem
{
     string name;
     //etc
}

そして、言います:

public class Car : MessageItem
{
    string Model;
    //etc
}

これはすべて機能し、次のようにして2つのタイプのいずれかを受け取ることができます:

if(myConnection.NextMessageType() == MessageType.Binary1)
{
     Employee e = (Employee)myConnection.ReadMessage();
}
if(myConnection.NextMessageType() == MessageType.Binary2)
{
    Car c = (Car)myConnection.ReadMessage();
}

クライアントが常にEmployee型を asbinary1およびCaras として送信する限りbinary2

オブジェクト/クラスの 3 番目のタイプを送信する場合は、現時点で dll に移動し、列挙型を追加する必要があります。binary3、dllを再構築してから、クライアントで再度派生さifせ、上記の受信コードで3番目の句を使用できます。

if(myConnection.NextMessageType() == MessageType.Binary3)
{
    Animal a = (Animal)myConnection.ReadMessage();
}

それでは最後に私の質問に!

DLL を再構築する必要がなく、クライアントが DLL を介して好きなだけ多くの異なるクラス型を送信でき、DLL の送信/受信メカニズム (クライアントから隠されている) が引き続き機能する方法はありますか? また、etcの長いリストはif messagetype == 1, 2 3悪いデザインを強調していると思いますが、より良いデザインが何であるかはわかりません.

ここまで来て、私が求めていることを理解できたなら、ありがとう! 解決策を本当に感謝します。

4

1 に答える 1

0

最も簡単な解決策は、MessageType 列挙を文字列に変更し、列挙を完全に取り除くことです。変化する:-

public void SendMessage(MessageType type, MessageItem message)

ちょうどに:-

public void SendMessage(MessageItem message)

次に、SendPacket を次のように変更します。

internal bool SendPacket(Packet p)
{
  bool sentOk = false;
  BinaryFormatter bin = new BinaryFormatter();
  try
  {
    bin.write (p.MessageItem.GetType ().Name); // or whatever the write/serialise function is called
    bin.Serialize(theNetworkStream, p);
  }
  catch etc..
}

次に、レシーバーは最初に文字列を読み取り、次にリフレクションを使用してその型のオブジェクトを作成し、次に疑似コードでオブジェクトにデシリアライズします。

string message_type = ethernet.readstring ();
Type item_type = convert_name_to_object_type;
ConstructorInfo constructor = item_type.GetConstructor ();
object item = constructor.Invoke ();
ethernet.Deserialise (item);
invoke MessageReceived event (item);

最後の部分では、 a を使用しSortedDicationary <message type name, message handler delegate>てメッセージを適切なハンドラーにディスパッチできます (ただし、これにより、ハンドラーは MessageItem パラメーターを正しいメッセージ型に型キャストする必要があります)。または、リフレクションを再度使用して、イーサネット経由で受信したタイプのパラメーターを 1 つ受け取る「HandleEthernetMessage」というメソッドを見つけます。SortedDicationary <message type name, method info>実行時の速度が向上し、最初の SortedDictionary の問題が解決されます。

于 2012-05-30T11:30:59.813 に答える