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)代码>做得有点太多了。你没有告诉我们它是干什么的,我做了个假设。请检查最新编辑。顺便说一句:你得到的错误实际上是个好消息!!!。它告诉您,消息
的一个实例已成功反序列化,现在存在于堆中。演员阵容是个问题。这个强制转换是通过反序列化
方法执行的,你没有给我们看使用对象obj=(新的BinaryFormatter())进行代码>反序列化(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);
}
}