1

さまざまなブロードキャスト メッセージを送信することで、単純なネットワーク プログラムを動作させようとしています。

最初の私のメッセージクラス:

[Serializable()]
public class Message<T>
{
    public enum MessageType
    {
        Broadcast,
        Unicast
    }

    private T _payload;
    private readonly MessageType _type;
    private readonly DateTime _createdOn = DateTime.Now;

    public MessageType Type
    {
        get { return _type; }
    }

    public T Payload
    {
        get { return _payload; }
        set { _payload = value; }
    }

    public DateTime CreatedOn
    {
        get { return _createdOn; }
    }
    private Message() { }
    private Message(T setPayload, MessageType type)
    {
        _payload = setPayload;
        _type = type;
    }

    public class Builder
    {
        private readonly T _payload;
        private MessageType _messageType = MessageType.Unicast;

        public Builder(T payload)
        {
            _payload = payload;
        }

        public Builder Broadcast()
        {
            _messageType = MessageType.Broadcast;
            return this;
        }

        public Message<T> Build()
        {
            Message<T> result = new Message<T>(_payload, _messageType);
            return result;
        }
    }
}

それから私は私のクラスを持っています:

[Serializable()]
public class HelloWorld
{
    public String HelloString { get; set; }
    public HelloWorld() { }
}

[Serializable()]
class HelloWorld2
{
    public String HelloString2 { get; set; }
    public HelloWorld2() { }
}

今、私は2つの方法SendHelloWorld()SendHelloWorld2().

typeName を含む文字列用に、Memorystream の最初の 32 バイトを予約しています。

internal void SendHelloWorld()
    {
        HelloWorld helloWorld = new HelloWorld();

        var message = new Message<HelloWorld>.Builder(helloWorld).Broadcast().Build();

        // implement broadcasting
        Stream memoryStream = new MemoryStream();
        byte[] buffer = ASCIIEncoding.ASCII.GetBytes("Messages.HelloWorld");

        memoryStream.Write(buffer, 0, buffer.Length);

        SerializationService.Serialize(memoryStream, message);
        SendBroadcastMessage(memoryStream);
    }

SendBroadCastMessage は、ストリームを byte[] に変換し、メッセージをブロードキャストします。

それらを受信するとき、メッセージが Typeof HelloWorld または HelloWorld2 であるかどうかを確認する必要があります

しかし、私はそれを機能させる方法をまだ見つけていません。文字列はタイプとして受け入れられます。スイッチケースを使用したくありません。その後、さらに多くのタイプのメッセージが追加されるためです。

private void UdpListener()
    {
        UdpClient listener = new UdpClient(9050, AddressFamily.InterNetwork);
        IPEndPoint iep = new IPEndPoint(IPAddress.Any, 9050);

        Stream inputStream = new MemoryStream(listener.Receive(ref iep));
        byte[] buffer = new byte[32];
        inputStream.Read(buffer, 0, 32);
        string type = ASCIIEncoding.ASCII.GetString(buffer,0,32);

        Message<type> message = _service.Deserialize<Message<HelloWorld>>(inputStream);

        Received(message.Payload);

        listener.Close();
    }
4

3 に答える 3

1

質問:何SerializationServiceですか?

うまくいけば、.NET標準のシリアル化、より正確にはBinaryFormatterを使用しています。SoapFormatterを使用している場合、ジェネリックは機能しません。この2つ以外を使用している場合は、どのようなシリアル化サービスか教えてください。

答えが好ましい場合(BinaryFormatter)、次のルートに進むことができます。

提案:

1)この抽象クラスを作成し、次のように拡張します。

 [Serializable()]
 public abstract class AbstractMessage {

     public object Payload { get { return this.GetPayload(); } }
     protected abstract object GetPayload();

 }

 [Serializable()]
 public class Message<T> : AbstractMessage
 {
     // .... etc ....
     public new T Payload
     {
         get { return _payload; }
         set { _payload = value; }
     }
     // .... etc ....
     protected override object GetPayload() { return this.Payload; }
 }  

2)これをやめる:

byte[] buffer = ASCIIEncoding.ASCII.GetBytes("Messages.HelloWorld");
memoryStream.Write(buffer, 0, buffer.Length);

3)そしてこれ:

byte[] buffer = new byte[32];
inputStream.Read(buffer, 0, 32);
string type = ASCIIEncoding.ASCII.GetString(buffer,0,32);

(.NETのシリアル化は、これまで以上に自明であり、大変な作業をさせてくれるからです)

4)受信アプリケーションで、次のようにします

private void UdpListener()
{
    // .... etc ....

    //object obj = _service.Deserialize<object>(inputStream);

    // this should now work perfectly (as long as you stopped writing the string into stream
    // from the client)
    object obj = (new BinaryFormatter()).Deserialize(inputStream);

    if (!(obj is AbstractMessage))
       // complain to yourself via exception, log or other things

    var message = obj as AbstractMessage;
    object payload = message.Payload;

    // here you can access on of two things:
    Type payloadType = payload.GetType();
    Type aproximatelySameType = message.GetType().GetGenericArguments()[0];

    // and you can honor this payload like an object or by casting it to whatever
    // you desire, or by reflection, or whatever
    Received(message.Payload);

    listener.Close();
}
于 2013-02-27T16:45:19.847 に答える
0

Static メソッドGetTypeを使用して、文字列から型を取得できます。

var myType = Type.GetType("SomeType");

ただし、その型が現在実行中のアセンブリにない限り、完全修飾型名を使用する必要があります。そうしないと、例外が発生します。

型の完全修飾アセンブリ名を確認したい場合は、Type オブジェクトのAssemblyQualifiedNameプロパティを調べることができます。

typeof(HelloWorld).AssemblyQualifiedName
于 2013-02-27T16:25:15.603 に答える
-1

UdpListener を変更しただけで動作します。

private void UdpListener()
    {
        _iep = new IPEndPoint(IPAddress.Any, 9050);
        _listener = new UdpClient(_iep);

        while (true)
        {
            Stream inputStream = new MemoryStream(_listener.Receive(ref _iep));

            dynamic msg = _service.Deserialize<object>(inputStream);

            Received(msg.Payload);
        }
    }

すべての回答をありがとう

于 2013-03-06T14:11:33.317 に答える