有没有specifing任何情况下对象转换回它原始类型的方法吗? [英] Is there a way cast an object back to it original type without specifing every case?

查看:280
本文介绍了有没有specifing任何情况下对象转换回它原始类型的方法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有不同的类型对象的数组,我用的BinaryWriter每个项目转换为等值的二进制这样我就可以通过网络发送的结构。



我目前做这样的事情。

 为(i = 0; I< tmpArrayList.Count;我++)
{$ b $对象b X = tmpArrayList [I]
如果(x.GetType()== typeof运算(字节))
{
wrt.Write((字节)x)的;
}
........



问题在于如果错过一个类型他们我的代码可能会在未来的突破。



我想做些什么等。

 对象x = tmpArrayList [I] 
wrt.Write(X);



但它不工作,除非我做的每一个演员。



编辑:



咨询问题的答案,这是我想出了功能后。为了测试这个函数发送数组到syslog。

 私人无效TxMsg(ArrayList的TxArray,ip地址ip地址)
{
字节[] = TXBUF新的字节[0];
INT SZ = 0; TXBUF
的foreach

// caculate大小(对象o在TxArray)
{
如果(邻为String)
{
SZ + =((字符串)(O))长度。
}
,否则如果(邻为byte [])
{
SZ + =((字节[])(O))长度。
}
,否则,如果(O是的char [])
{
SZ + =((CHAR [])(O))长度。
}
,否则//照顾非数组
{
SZ + = Marshal.SizeOf(O);
}
}
TXBUF =新的字节[深圳]

System.IO.MemoryStream stm_w =新System.IO.MemoryStream(TXBUF,0,txbuf.Length);
System.IO.BinaryWriter WRT =新System.IO.BinaryWriter(stm_w);

的foreach(对象o在TxArray)
{
布尔otypefound = FALSE;如果(邻为String)//字符串需要发送的每字符
{
一个字节
otypefound = TRUE;
线St =(字符串)O;
的for(int i = 0; I< st.Length;我++)
{
wrt.Write((字节)ST [i]);
}
}
,否则
{
的foreach(MethodInfo的MI在typeof运算(的BinaryWriter).GetMethods())
{
如果(MI 。名称==写入)
{
的ParameterInfo [] =圆周率mi.GetParameters();
如果((pi.Length == 1)及及(PI [0] == .ParameterType o.GetType()))
{
otypefound = TRUE;
mi.Invoke(WRT,新的对象[] {Ø});
}
}
}
}
如果(otypefound ==假)
{
抛出新的InvalidOperationException异常(无法写入类型的数据+ o.GetType()全名)。
}
}
IPEndPoint端点=新IPEndPoint(ip地址,514); //日志端口
UdpClient udpClient_txmsg =新UdpClient();
udpClient_txmsg.Send(TXBUF,txbuf.Length,终点); //发送UDP数据包到syslog
}


解决方案

下面是的BinaryWriter使用反射的解决方案。



这基本上是扫描的BinaryWriter名为写带一个参数的方法,然后建立一个字典,其中方法处理哪种类型,然后为每个对象来写,找到正确的方法,并调用它的作家。



脏,你应该寻找做整个事情的更好的方法(不只是写作部分),但它应该适合当前需要的工作:

 使用System.IO; 
使用系统;
使用的System.Reflection;
使用System.Collections.Generic;
命名空间ConsoleApplication14
{
公共类节目
{
公共静态无效的主要()
{
字典<类型,MethodInfo的>映射=新词典<类型,MethodInfo的>();
的foreach(MethodInfo的MI在typeof运算(的BinaryWriter).GetMethods())
{
如果(mi.Name ==写入)
{
的ParameterInfo [] PI = mi.GetParameters();
如果(pi.Length == 1)
映射[PI [0] .ParameterType] = MI;
}
}

名单,LT;对象> someData =新的List<对象>();
someData.Add((字节)10);
someData.Add((Int32)已10);
someData.Add((双人间)10);
someData.Add((夏亚)10);
someData.Add(测试);使用(的FileStream文件=新的FileStream(@C:\test.dat,FileMode.Create,FileAccess.ReadWrite))


使用(的BinaryWriter作家=新的BinaryWriter(文件) )
{
的foreach(对象o在someData)
{
MethodInfo的MI;
如果(mapping.TryGetValue(o.GetType(),出MI))
{
mi.Invoke(作家,新的对象[] {Ø});
}
,否则
抛出新的InvalidOperationException异常(无法写入类型的数据+ o.GetType()全名);
}
}
}
}
}


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             
  }

解决方案

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:

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);
                }
            }
        }
    }
}

这篇关于有没有specifing任何情况下对象转换回它原始类型的方法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆