C# 获取流中泛型类的类型

C# 获取流中泛型类的类型,c#,generics,serialization,stream,C#,Generics,Serialization,Stream,我试图通过发送不同的广播信息来让一个简单的网络程序工作 首先,我的消息类: [Serializable()] public class Message<T> { public enum MessageType { Broadcast, Unicast } private T _payload; private readonly MessageType _type; private readonly Da

我试图通过发送不同的广播信息来让一个简单的网络程序工作

首先,我的消息类:

[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;
        }
    }
}
现在我有两个方法
SendHelloWorld()
SendHelloWorld2()

我将Memorystream的前32个字节保留为包含typeName的字符串

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);
    }
内部void SendHelloWorld()
{
HelloWorld HelloWorld=新HelloWorld();
var message=new message.Builder(helloWorld.Broadcast().Build();
//实施广播
Stream memoryStream=新的memoryStream();
byte[]buffer=ascienceoding.ASCII.GetBytes(“Messages.HelloWorld”);
memoryStream.Write(缓冲区,0,缓冲区长度);
SerializationService.Serialize(内存流、消息);
发送广播消息(memoryStream);
}
SendBroadCastMessage只是将流转换为字节[],并广播消息

当收到它们时,我必须检查消息的类型是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();
    }
private void UdpListener()
{
UdpClient侦听器=新的UdpClient(9050,AddressFamily.InterNetwork);
IPEndPoint iep=新IPEndPoint(IPAddress.Any,9050);
Stream inputStream=新的MemoryStream(listener.Receive(ref iep));
字节[]缓冲区=新字节[32];
读取(缓冲区,0,32);
字符串类型=ascienceoding.ASCII.GetString(缓冲区,0,32);
Message Message=\服务.反序列化(inputStream);
已接收(消息有效载荷);
listener.Close();
}

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

但是,除非该类型当前在执行程序集中,否则必须使用。否则你会得到一个例外

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

typeof(HelloWorld).AssemblyQualifiedName

问题:什么是
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; }
 }  
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();
}
private void UdpListener()
{
//……等等。。。。
//对象obj=_服务.反序列化(inputStream);
//现在应该可以很好地工作了(只要您停止将字符串写入流中)
//(来自客户)
对象obj=(新的BinaryFormatter())。反序列化(inputStream);
如果(!(obj是抽象消息))
//通过异常、日志或其他事情向自己抱怨
var message=obj作为抽象消息;
对象有效载荷=message.payload;
//在这里,您可以访问以下两种内容之一:
类型payloadType=payload.GetType();
类型aproximatelySameType=message.GetType().GetGenericArguments()[0];
//你可以像对待一个物体一样尊重这个有效载荷,或者把它扔到任何东西上
//你的欲望,或是通过思考,或是别的什么
已接收(消息有效载荷);
listener.Close();
}

让它正常工作只是改变了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);
        }
    }
private void UdpListener()
{
_iep=新的IPEndPoint(IPAddress.Any,9050);
_侦听器=新的UdpClient(_iep);
while(true)
{
Stream inputStream=新的MemoryStream(_listener.Receive(ref_iep));
动态消息=_服务.反序列化(inputStream);
接收(消息有效载荷);
}
}

感谢您提供了太长而无法阅读的所有答案

,您可以用简单而简短的文字简化您的问题,但myType是一个空引用。如果我使用字符串temp=“Messages.HelloWorld,Grid.Node”Grid.Node是我的程序集名称,它也是一个空引用。是的,我正在使用binaryFormatter序列化,但是如果我尝试反序列化对象,我会收到一个错误。无法将类型为“Grid.Node.Messages.Message
1[Grid.Node.Messages.HelloWorld]”的对象强制转换为类型为“Grid.Node.Messages.Message
1[System.object]”。明天将查找您在UDP侦听器中提到的方法:
\u service.Deserialize(inputStream)做得有点太多了。你没有告诉我们它是干什么的,我做了个假设。请检查最新编辑。顺便说一句:你得到的错误实际上是个好消息!!!。它告诉您,
消息
的一个实例已成功反序列化,现在存在于堆中。演员阵容是个问题。这个强制转换是通过
反序列化
方法执行的,你没有给我们看反序列化(inputStream)
而且它应该工作得很好,只要您不再从客户端发送前导字符串——还有一个问题:我想在payloadType中强制转换var消息。例如,如果var message的类型是HelloWorld,我想这样强制转换:var newMessage=(message))message;但是我没有找到一种方法,因为我不知道代码块是如何写在注释中的:
var message=obj as AbstractMessage;如果(message.Payload是HelloWorld){HelloWorld obj1=(HelloWorld)message.Payload;var morespectmsg=(message)message;HelloWorld obj2_equaltobj1=morespectmsg.Payload;}否则{//blah}
。这就是你要找的吗?
byte[] buffer = new byte[32];
inputStream.Read(buffer, 0, 32);
string type = ASCIIEncoding.ASCII.GetString(buffer,0,32);
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();
}
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);
        }
    }