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() { }
}

现在我有两种方法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

但我还没有找到让它工作的方法,字符串被接受为类型,我不想使用 switch-case,因为之后会添加更多类型的消息。

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

您可以使用静态方法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 回答