有没有一种方法可以将对象强制转换回其原始类型而不指定每种情况?
我有一个不同类型对象的数组,我使用 BinaryWriter 将每个项目转换为其二进制等效项,以便我可以通过网络发送该结构。
我目前正在做类似的事情,
for ( i=0;i<tmpArrayList.Count;i++)
{
object x=tmpArrayList[i];
if (x.GetType() == typeof(byte))
{
wrt.Write((byte)x);
}
........
问题是,如果错过了它们的类型,我的代码将来可能会崩溃。
我想做类似的事情。
object x=tmpArrayList[i];
wrt.Write(x);
但除非我完成每个演员表,否则它不起作用。
编辑:
在咨询了答案之后,这就是我对该功能的想法。 为了测试此函数将数组发送到系统日志。
private void TxMsg(ArrayList TxArray,IPAddress ipaddress)
{
Byte[] txbuf=new Byte[0];
int sz=0;
// caculate size of txbuf
foreach (Object o in TxArray)
{
if ( o is String )
{
sz+=((String)(o)).Length;
}
else if ( o is Byte[] )
{
sz+=((Byte[])(o)).Length;
}
else if ( o is Char[] )
{
sz+=((Char[])(o)).Length;
}
else // take care of non arrays
{
sz+=Marshal.SizeOf(o);
}
}
txbuf = new Byte[sz];
System.IO.MemoryStream stm_w = new System.IO.MemoryStream( txbuf, 0,txbuf.Length);
System.IO.BinaryWriter wrt = new System.IO.BinaryWriter( stm_w );
foreach (Object o in TxArray)
{
bool otypefound=false;
if (o is String) // strings need to be sent one byte per char
{
otypefound=true;
String st=(String)o;
for(int i=0;i<st.Length;i++)
{
wrt.Write((byte)st[i]);
}
}
else
{
foreach (MethodInfo mi in typeof(BinaryWriter).GetMethods())
{
if (mi.Name == "Write")
{
ParameterInfo[] pi = mi.GetParameters();
if ((pi.Length == 1)&&(pi[0].ParameterType==o.GetType()))
{
otypefound=true;
mi.Invoke(wrt, new Object[] { o });
}
}
}
}
if(otypefound==false)
{
throw new InvalidOperationException("Cannot write data of type " + o.GetType().FullName);
}
}
IPEndPoint endpoint = new IPEndPoint(ipaddress, 514); //syslog port
UdpClient udpClient_txmsg = new UdpClient();
udpClient_txmsg.Send(txbuf, txbuf.Length,endpoint); // send udp packet to syslog
}
I have an array of different type objects and I use a BinaryWriter to convert each item to its binary equivalent so I can send the structure over the network.
I currently do something like
for ( i=0;i<tmpArrayList.Count;i++)
{
object x=tmpArrayList[i];
if (x.GetType() == typeof(byte))
{
wrt.Write((byte)x);
}
........
The problem is that if miss a type them my code might break in the future.
I would like to do something like.
object x=tmpArrayList[i];
wrt.Write(x);
but it doesn't work unless I do each cast.
Edit:
After consulting the answers this is what I came up with for the function. For testing this function sends the array to syslog.
private void TxMsg(ArrayList TxArray,IPAddress ipaddress)
{
Byte[] txbuf=new Byte[0];
int sz=0;
// caculate size of txbuf
foreach (Object o in TxArray)
{
if ( o is String )
{
sz+=((String)(o)).Length;
}
else if ( o is Byte[] )
{
sz+=((Byte[])(o)).Length;
}
else if ( o is Char[] )
{
sz+=((Char[])(o)).Length;
}
else // take care of non arrays
{
sz+=Marshal.SizeOf(o);
}
}
txbuf = new Byte[sz];
System.IO.MemoryStream stm_w = new System.IO.MemoryStream( txbuf, 0,txbuf.Length);
System.IO.BinaryWriter wrt = new System.IO.BinaryWriter( stm_w );
foreach (Object o in TxArray)
{
bool otypefound=false;
if (o is String) // strings need to be sent one byte per char
{
otypefound=true;
String st=(String)o;
for(int i=0;i<st.Length;i++)
{
wrt.Write((byte)st[i]);
}
}
else
{
foreach (MethodInfo mi in typeof(BinaryWriter).GetMethods())
{
if (mi.Name == "Write")
{
ParameterInfo[] pi = mi.GetParameters();
if ((pi.Length == 1)&&(pi[0].ParameterType==o.GetType()))
{
otypefound=true;
mi.Invoke(wrt, new Object[] { o });
}
}
}
}
if(otypefound==false)
{
throw new InvalidOperationException("Cannot write data of type " + o.GetType().FullName);
}
}
IPEndPoint endpoint = new IPEndPoint(ipaddress, 514); //syslog port
UdpClient udpClient_txmsg = new UdpClient();
udpClient_txmsg.Send(txbuf, txbuf.Length,endpoint); // send udp packet to syslog
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不可以。必须在编译时知道强制转换,但实际类型只有在执行时才知道。
但请注意,有一种更好的方法可以调用 GetType 来测试类型。 而不是:
使用:
编辑:回答额外的问题:
“所有类型是什么?” 好吧,看看 BinaryWriter 的文档,我想......
“我需要担心字节和字节吗?” 不,byte 是 C# 中 System.Byte 的别名。 他们是同一类型。
No. The cast has to be known at compile-time, but the actual type is only known at execution time.
Note, however, that there's a better way of testing the type calling GetType. Instead of:
Use:
EDIT: To answer the extra questions:
"What are all the types?" Well, look down the docs for BinaryWriter, I guess...
"Do I need to worry about byte and Byte?" No, byte is an alias for System.Byte in C#. They're the same type.
这是使用反射的 BinaryWriter 解决方案。
这基本上会扫描 BinaryWriter 中名为 Write 的方法,该方法只接受一个参数,然后构建一个字典,其中的方法处理哪种类型,然后对于每个要写入的对象,找到正确的方法并在编写器上调用它。
肮脏,你可能应该寻找更好的方法来完成整个事情(而不仅仅是写作部分),但它应该适合你当前的需求:
Here is a solution for BinaryWriter that uses reflection.
This basically scans BinaryWriter for methods named Write that takes exactly one parameter, then builds a dictionary of which method handles which type, then for each object to write, finds the right method and calls it on the writer.
Dirty, and you should probably look for better ways of doing the whole thing (not just the writing part), but it should work for your current needs:
乔恩是对的,但我还有另一个想法,你可能会觉得有用。 您是否考虑过在每个对象的传输中添加另一个字节,然后使用该字节作为类型代码,告诉您在另一端将其转换为什么?
Jon's right, but I had another thought that you may find useful. Have you considered adding in another byte to the transmission of each object, then using that byte as a type code, telling you what to cast it to on the other end?
您是否考虑过使用 BinaryFormatter 而不是 BinaryWriter?
优点
缺点
在内部使用序列化,因此:
Have you considered using a BinaryFormatter instead of the BinaryWriter?
Advantages
Disadvantages
Uses Serialization internally, therefore:
您要求的是动态调度,而C# 3.0没有它。
您至少应该使用运行时检查来验证您没有丢失类型。
如果您有一个从类型映射到处理函数的字典,您也许可以做一些聪明的事情。 您可以在一处填写所有处理功能的映射。 与在处理发生的任何地方编写开关相比,您更有可能做到这一点。
What you're asking for is Dynamic Dispatch, and C# 3.0 doesn't have it.
You should at least use a runtime check to verify that you aren't missing a type.
You may be able to do something clever where you have a
Dictionary
that maps from types to processing functions. You can fill in the mapping for all processing functions in one place. You have a better chance of getting this right than if you write a switch wherever the processing happens.这是需要一种名为 Double Dispatch 的情况。
我假设 wrt 对象是您自己编写的对象(假设它是 Writer 类型)。 您可以执行以下操作:
Writer 所做的就是分派回输入,告诉它使用它(Writer)进行写入,但是这是针对该对象完成的,无法提前知道。
This is a case of needing something called Double Dispatch.
I'm going to assume that the wrt object is one you wrote yourself (Let's say it is of type Writer). Here is what you could do:
What Writer is doing is dispatching back to the input, telling it to use it (the Writer) to write, however that is done for that object, which cannot be known ahead of time.