如何使用单个函数枚举c#中的这些数据结构?

时间:2015-12-19 02:51:15

标签: c#

我有一些数据结构,其中包含诸如“Tcpv4Endpoint”之类的信息。和' TCPV6Endpoint'

数据结构是:

[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID
{
    public uint state;
    public uint localAddr;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] localPort;
    public uint remoteAddr;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] remotePort;
    public uint owningPid;
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCP6ROW_OWNER_PID
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] localAddr;
    public uint localScopeId;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] localPort;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] remoteAddr;
    public uint remoteScopeId;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] remotePort;
    public uint state;
    public uint owningPid;
}

可以想象,我在两个不同的函数中使用这两个数据结构来填充列表视图。我想将这两个结构的添加组合成一个共同的功能。但我无法弄清楚如何在这两个结构之间进行类型转换并访问字段。

我想概括的功能是这样的:

public void addTCPV6ConnectionsToListView()
{
    int i;
    string strErrorMessage = "";
    List<MIB_TCP6ROW_OWNER_PID> tcpRowTable = ...//data populated...//
    MIB_TCP6ROW_OWNER_PID row;

    //...Error handling case removed for ease of reading ...  
    ListViewItem[] lItem = new ListViewItem[tcpRowTable.Count];
    listView1.BeginUpdate();
    for (i = 0; i < tcpRowTable.Count; i++)
    {
        row = tcpRowTable[i];
            lItem[i].Text = Process.GetProcessById((int)row.ProcessId).ProcessName + ".exe";
        lItem[i].SubItems.Add(row.ProcessId.ToString());
        lItem[i].SubItems.Add("TCPV6");
        lItem[i].SubItems.Add("[ " + expandCompressedIPv6Addr(row.LocalAddress.ToString()) + " ]"); //Similiar fields in TCPv4 and TCPv6 structures , except for one or two fields
        lItem[i].SubItems.Add(row.LocalPort.ToString());
        lItem[i].SubItems.Add("[ " + expandCompressedIPv6Addr(row.RemoteAddress.ToString()) + " ]");
        lItem[i].SubItems.Add(row.RemotePort.ToString());
        lItem[i].SubItems.Add(getStateInformation(row.State));
    }
    listView1.Items.AddRange(lItem);
    listView1.EndUpdate();

}

是否可以这样做?

2 个答案:

答案 0 :(得分:1)

最好的选择是定义一个通用接口。

arr[4]

使用此解决方案,您必须记住,接口只能定义属性,而不能定义字段。因此,您必须将您定义的字段更改为属性:

而不是

public interface MIB_OWNER_PID
{
    public uint state {get; set; }
    public uint localAddr { get; set; }
    public byte[] localPort { get; set; }
    public uint remoteAddr { get; set; }
    public byte[] remotePort { get; set; }
    public uint owningPid { get; set; }
}

public uint state;

另一种选择是在使用它们之前简单地将对象强制转换为public uint state { get; set;} 。然后你可以使用任何属性,字段或方法,编译器不会抱怨,因为它们是在运行时进行评估的。因此,如果属性,字段或方法在运行时不存在,您仍将获得异常。

dynamic

答案 1 :(得分:0)

我假设您的specfic [StructLayout]是因为您还希望/需要能够支持memcpy类型的操作。如果是这种情况,您可以在特定字段之前添加方法/属性并与接口结合使用。

public interface MIB_OWNER_PID
{
   public void update (uint state,uint localaddr, byte[] localport, /*etc*/)
   public uint localAddress { get; set; }
}


[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID : MIB_OWNER_PID
{
   public uint state;
   public uint localAddr;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
   public byte[] localPort;
   public uint remoteAddr;
   [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
   public byte[] remotePort;
   public uint owningPid;

   public void update (uint state,uint localaddr, byte[] localport, /*etc*/)
   {

   }

   public uint localAddress 
   {
      get { return localAddr;} 
      set { localAddr = value}
    }
}

使用'simple'属性并使用空{get; set;}因为您可能无法控制如何生成支持字段。

在你的结构上使用方法的好处是你可以回复polimorphism以“做正确的事”并实现ipv4和ipv6方式。 (只要方法具有相同的签名。如果你依赖ipv6特定的字段,那么这不能很好地工作)。