C# 有没有一种方法可以将对象强制转换回其原始类型,而不必指定每种情况?
我有一个不同类型对象的数组,我使用BinaryWriter将每个项目转换为其二进制等价物,以便通过网络发送结构 我现在做的是C# 有没有一种方法可以将对象强制转换回其原始类型,而不必指定每种情况?,c#,casting,syslog,udpclient,C#,Casting,Syslog,Udpclient,我有一个不同类型对象的数组,我使用BinaryWriter将每个项目转换为其二进制等价物,以便通过网络发送结构 我现在做的是 for ( i=0;i<tmpArrayList.Count;i++) { object x=tmpArrayList[i]; if (x.GetType() == typeof(byte)) { wrt.Write((byte)x); } ........ 但除非我每次都投,否则就没用了 编辑: 在查阅了答案之后,这就
for ( i=0;i<tmpArrayList.Count;i++)
{
object x=tmpArrayList[i];
if (x.GetType() == typeof(byte))
{
wrt.Write((byte)x);
}
........
但除非我每次都投,否则就没用了
编辑:
在查阅了答案之后,这就是我为函数所想到的。为了测试此函数,将数组发送到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
}
private void TxMsg(ArrayList TxArray,IPAddress-IPAddress)
{
字节[]txbuf=新字节[0];
int sz=0;
//计算txbuf的尺寸
foreach(TxArray中的对象o)
{
if(o是字符串)
{
sz+=((字符串)(o))长度;
}
else if(o是字节[])
{
sz+=((字节[])(o))。长度;
}
else if(o是字符[])
{
sz+=((Char[])(o))。长度;
}
else//处理非数组
{
sz+=Marshal.SizeOf(o);
}
}
txbuf=新字节[sz];
System.IO.MemoryStream stm_w=新的System.IO.MemoryStream(txbuf,0,txbuf.Length);
System.IO.BinaryWriter wrt=新的System.IO.BinaryWriter(stm_w);
foreach(TxArray中的对象o)
{
bool-otypefound=false;
if(o是String)//字符串需要每个字符发送一个字节
{
otypefound=true;
字符串st=(字符串)o;
对于(int i=0;iNo)。强制转换必须在编译时已知,但实际类型仅在执行时已知
但是,请注意,有一种更好的方法可以测试调用GetType的类型。而不是:
if (x.GetType() == typeof(byte))
使用:
编辑:回答额外的问题:
“所有的类型都是什么?”好吧,我想在文档中查找BinaryWriter
“我需要担心字节和字节吗?”不,字节是系统的别名。C#中的字节。它们是相同的类型。乔恩是对的,但我有另一个想法,你可能会发现它很有用。你是否考虑过在每个对象的传输中添加另一个字节,然后将该字节用作类型代码,告诉你将其转换到另一端的内容?你要求的是Dyna麦克风调度,而C#3.0没有
您至少应该使用运行时检查来验证是否缺少类型
如果你有一个从类型映射到处理函数的字典,你也许可以做一些聪明的事情。你可以在一个地方填写所有处理函数的映射。你有更好的机会做到这一点,而不是在处理发生的任何地方写一个开关。这是一个需要一些东西的情况g打电话来
我将假设wrt对象是您自己编写的对象(假设它是Writer类型)
class Writer
{
void write(byte b)
{
// write bytes here
}
void write(Writable something)
{
something.writeOn(this);
}
}
interface Writeable
{
void writeOn(Writer writer);
}
class SomeObject implements Writeable
{
private Object someData;
private Object moreData;
void writeOn(Writer writer)
{
writer.write(convertToByte(someData));
writer.write(convertToByte(moreData));
}
}
class AnotherObject implements Writeable
{
private int x;
private int y;
private int z;
void writeOn(Writer writer)
{
writer.write((byte)x);
writer.write((byte)y);
writer.write((byte)z);
}
}
Writer所做的是将其发送回输入,告诉它使用它(Writer)进行写入,但是这是为该对象完成的,而该对象无法提前知道。您是否考虑过使用a而不是BinaryWriter
优势
- 您可以传递对象(即任何对象),因此它可以解决您的铸造问题
- 自动类型管理(实际上将类型头写入流)
- 还支持复杂的引用类型
缺点
在内部使用序列化,因此:
- 可能慢一点
- 字节流变大(因为类型头)
- 您无法控制字节格式,因此在互操作场景中无法选择
- 潜在的版本问题(序列化类型的不同程序集版本之间的兼容性)
- 需要序列化代码访问权限(与部分信任场景相关)
这里是一个使用反射的BinaryWriter解决方案
这基本上是扫描BinaryWriter,查找只接受一个参数的方法Write,然后构建一个字典,确定哪个方法处理哪种类型,然后为每个要写入的对象找到正确的方法并在writer上调用它
肮脏,你可能应该寻找更好的方法来完成整个工作(不仅仅是写作部分),但它应该适合你当前的需要:
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
namespace ConsoleApplication14
{
public class Program
{
public static void Main()
{
Dictionary<Type, MethodInfo> mapping = new Dictionary<Type, MethodInfo>();
foreach (MethodInfo mi in typeof(BinaryWriter).GetMethods())
{
if (mi.Name == "Write")
{
ParameterInfo[] pi = mi.GetParameters();
if (pi.Length == 1)
mapping[pi[0].ParameterType] = mi;
}
}
List<Object> someData = new List<Object>();
someData.Add((Byte)10);
someData.Add((Int32)10);
someData.Add((Double)10);
someData.Add((Char)10);
someData.Add("Test");
using (FileStream file = new FileStream(@"C:\test.dat", FileMode.Create, FileAccess.ReadWrite))
using (BinaryWriter writer = new BinaryWriter(file))
{
foreach (Object o in someData)
{
MethodInfo mi;
if (mapping.TryGetValue(o.GetType(), out mi))
{
mi.Invoke(writer, new Object[] { o });
}
else
throw new InvalidOperationException("Cannot write data of type " + o.GetType().FullName);
}
}
}
}
}
使用System.IO;
使用制度;
运用系统反思;
使用System.Collections.Generic;
命名空间控制台应用程序14
{
公共课程
{
公共静态void Main()
{
字典映射=新字典();
foreach(typeof中的MethodInfo mi(BinaryWriter).GetMethods())
{
如果(mi.Name==“写入”)
{
ParameterInfo[]pi=mi.GetParameters();
如果(pi.Length==1)
映射[pi[0]。参数类型]=mi;
}
}
List someData=新列表();
someData.Add((字节)10);
添加((Int32)10);
添加((双)10);
someData.Add((Char)10);
添加(“测试”);
使用(FileStream file=newfilestream(@“C:\test.dat”、FileMode.Create、FileAccess.ReadWrite))
使用(BinaryWriter=新的BinaryWriter(文件))
{
foreach(someData中的对象o)
{
MethodInfo-mi;
if(mapping.TryGetValue(o.GetType(),out mi))
{
调用(writer,新对象[]{o});
}
其他的
抛出新的InvalidOperationException(“无法写入类型为“+o.GetType().FullName”的数据);
}
}
}
}
}
迫不及待地等待C#4.0。你也许应该给他看一个例子,说明如何使用dynamic关键字在C#4.0中实现它?我不知道是否可以在C#4.0中实现。事实上,我怀疑OP需要的是双动态d
class Writer
{
void write(byte b)
{
// write bytes here
}
void write(Writable something)
{
something.writeOn(this);
}
}
interface Writeable
{
void writeOn(Writer writer);
}
class SomeObject implements Writeable
{
private Object someData;
private Object moreData;
void writeOn(Writer writer)
{
writer.write(convertToByte(someData));
writer.write(convertToByte(moreData));
}
}
class AnotherObject implements Writeable
{
private int x;
private int y;
private int z;
void writeOn(Writer writer)
{
writer.write((byte)x);
writer.write((byte)y);
writer.write((byte)z);
}
}
using System.IO;
using System;
using System.Reflection;
using System.Collections.Generic;
namespace ConsoleApplication14
{
public class Program
{
public static void Main()
{
Dictionary<Type, MethodInfo> mapping = new Dictionary<Type, MethodInfo>();
foreach (MethodInfo mi in typeof(BinaryWriter).GetMethods())
{
if (mi.Name == "Write")
{
ParameterInfo[] pi = mi.GetParameters();
if (pi.Length == 1)
mapping[pi[0].ParameterType] = mi;
}
}
List<Object> someData = new List<Object>();
someData.Add((Byte)10);
someData.Add((Int32)10);
someData.Add((Double)10);
someData.Add((Char)10);
someData.Add("Test");
using (FileStream file = new FileStream(@"C:\test.dat", FileMode.Create, FileAccess.ReadWrite))
using (BinaryWriter writer = new BinaryWriter(file))
{
foreach (Object o in someData)
{
MethodInfo mi;
if (mapping.TryGetValue(o.GetType(), out mi))
{
mi.Invoke(writer, new Object[] { o });
}
else
throw new InvalidOperationException("Cannot write data of type " + o.GetType().FullName);
}
}
}
}
}