首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >获取流中泛型类的类型

获取流中泛型类的类型
EN

Stack Overflow用户
提问于 2013-02-28 00:16:53
回答 3查看 1.7K关注 0票数 1

我正在试着通过发送不同的广播消息来让一个简单的网络程序工作。

First my Message Class:

代码语言:javascript
运行
复制
[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;
        }
    }
}

然后我有我的课程:

代码语言:javascript
运行
复制
[Serializable()]
public class HelloWorld
{
    public String HelloString { get; set; }
    public HelloWorld() { }
}

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

现在我有两个方法SendHelloWorld()SendHelloWorld2()

我将我的内存流的前32个字节保留给一个包含typeName的字符串。

代码语言:javascript
运行
复制
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[]并广播消息。

当我收到它们时,我必须检查消息的类型是HelloWorld还是HelloWorld2

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

代码语言:javascript
运行
复制
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();
    }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-06 22:11:33

只需更改UdpListener即可正常工作:

代码语言:javascript
运行
复制
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);
        }
    }

感谢你所有的回答

票数 -1
EN

Stack Overflow用户

发布于 2013-02-28 00:45:20

问:什么是SerializationService

希望您使用的是.NET标准序列化,更准确地说是: BinaryFormatter。如果你使用的是SoapFormatter,那么泛型就不会起作用。如果您使用的不是这两个服务,请告诉我们它是什么类型的序列化服务。

如果答案是肯定的(BinaryFormatter),您可以采用以下方法。

建议:

1)创建这个抽象类,并让您的类像这样扩展它:

代码语言:javascript
运行
复制
 [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)停止这样做:

代码语言:javascript
运行
复制
byte[] buffer = ASCIIEncoding.ASCII.GetBytes("Messages.HelloWorld");
memoryStream.Write(buffer, 0, buffer.Length);

3)和这个:

代码语言:javascript
运行
复制
byte[] buffer = new byte[32];
inputStream.Read(buffer, 0, 32);
string type = ASCIIEncoding.ASCII.GetString(buffer,0,32);

(因为.NET序列化比您以往任何时候都更容易理解,让它为您完成繁重的工作)

4)在您的接收应用程序中,执行以下操作

代码语言:javascript
运行
复制
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();
}
票数 1
EN

Stack Overflow用户

发布于 2013-02-28 00:25:16

可以使用静态方法GetType从字符串中获取类型

代码语言:javascript
运行
复制
var myType = Type.GetType("SomeType");

但是,除非该类型当前在执行程序集中,否则必须使用fully qualified type name。否则你会得到一个异常。

如果要查看类型的完全限定程序集名称,可以检查类型对象的AssemblyQualifiedName属性。

代码语言:javascript
运行
复制
typeof(HelloWorld).AssemblyQualifiedName
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15116943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档