3

大家好,我对 C# .NET 中的代码有疑问,我正在使用 DLL 连接到 OPC 服务器,该 DLL 在 VB.NET 项目中使用并且完全没有问题。

我正在尝试在 ListBox 中显示可用服务器的列表,VB.NET(和工作)中使用的代码是这个:

Dim AllOPCServers As Object
AllOPCServers = AnOPCServer.GetOPCServers

' Load the list returned into the List box for user selection
Dim i As Short
For i = LBound(AllOPCServers) To UBound(AllOPCServers)
    AvailableOPCServerList.Items.Add(AllOPCServers(i))
Next i

我写了这个在 C# 应用程序中使用

try
{
    var _listOPCServer = _OPCServer.GetOPCServers();
    foreach(var i in _listOPCServer)
    {
        string serverName = (string)i;
        listServers.Items.Add(serverName);
    }             
}
catch (Exception exc)
{
    lstMsg.Items.Add(DateTime.Now + " Error al Obtener Lista de OPC's: " + exc.Message);
}

在本地选项卡上的调试模式下显示:

_listOPCServer | {字符串[1..2]} | 动态 {string[]} |

[1]        |  "Server01"    | string  
[2]        |  "Server02"    | string

更新:

我在“foreach(var i in _listOPCServer)”行中收到错误

无法将对象类型“System.String[*]”转换为“System.String[]”

这才是真正的错误。

我确定我做错了什么,有人可以帮助我吗?

4

3 回答 3

4

好的,我找到了解决这个问题的方法,这只是你建议的一个模式

 Array _listOPCServer = (Array)(object)_OPCServer.GetOPCServers();               

            foreach(object i in _listOPCServer)
            {
                string serverName = (string)i;
                listServers.Items.Add(serverName);
            }             

我只在声明中添加了(对象)并且工作正常,现在我可以按照我想要的方式显示服务器列表

或者也这样做

Array _listOPCServer = (Array)(object)_OPCServer.GetOPCServers();               

            foreach(object i in _listOPCServer)
            {
                listServers.Items.Add(i);
            }

再次感谢您的帮助和时间!

于 2012-09-14T19:26:44.803 回答
2

VB.NET 在处理不一致的数组类型方面要精明得多。不要犹豫,使用它,.NET 使语言之间的互操作变得容易。

问题在于 OPC 是基于 COM 的标准。您正在使用的服务器正在返回一个 SAFEARRAY,其下限不一致,第一个索引是 1。不是 0。在 COM 中并不罕见,在 0 和 1 之间选择作为第一个数组索引就像字节序问题或争论是否番茄是一种水果或蔬菜(它是一种水果。而 little-endian 是一种正确的蔬菜)。

然而,0 作为下界是 C# 在处理一维数组时所坚持的。它需要一个“向量”,一种独特的数组类型,它始终具有一个下限为 0 的维度。在 .NET 运行时中进行了大量优化。你得到的不匹配,所以被映射到一个一维的多维数组。不是可以用 C# 语言表达的数组类型。

可以在 C# 中破解它,但您必须明确使用 Array 类型。像这样的东西,为了清楚起见:

Array servers = (Array)_OPCServer.GetOPCServers();
int first = servers.GetLowerBound(0);
int last = servers.GetUpperBound(0);
for (int ix = first; ix <= last; ++ix) {
    var elem = (string)servers.GetValue(ix);
    // etc..
}
于 2012-09-14T00:02:57.723 回答
1

虽然 Hans 在区分从零开始的数组和非从零开始的数组之间的区别是正确的,但我仍然不明白您为什么会遇到这种异常。

我的猜测是您声明_OPCServeras dynamic,它将类型绑定推迟到运行时。_listOPCServer也是如此dynamic

由于您正在遍历数组并提取strings,编译器可能会尝试将对象强制转换为string[]为 Hans 指出的无效的对象。

您应该能够转换_listOPCServer为 anArray并按foreach原样使用:

Array _listOPCServer = (Array)(_OPCServer.GetOPCServers());
foreach(var i in _listOPCServer)
{
    // etc.
于 2012-09-14T01:11:10.453 回答