迭代ActiveX集合对象与c#的后期绑定互操作(COMAdminCatalogCollection)

本文关键字:绑定 互操作 COMAdminCatalogCollection 集合 ActiveX 对象 迭代 | 更新日期: 2023-09-27 18:14:37

我需要在c#中使用后期绑定互操作迭代COM+/ActiveX集合对象。在这一刻,我需要迭代COMAdmin.COMAdminCatalogCollection,从COMAdmin.COMAdminCatalogGetCollection("Applications")方法。但是,由于它是一个POC与其他专有的COM+/ActiveX对象一起使用,我需要用后期绑定来完成这项工作。我应该如何将我的object对象框成可迭代的?

<标题> COMPlus.cs h1> COMAdminCatalog.cs h1> COMAdminCatalogCollection.cs h1> Toolbox.cs h1> 辑

我需要它兼容。net 2.0(最多3.5),所以动态不适合我。

迭代ActiveX集合对象与c#的后期绑定互操作(COMAdminCatalogCollection)

您在c#中使用foreach关键字,就像您通常会迭代集合一样。DLR知道如何自动将其映射到ICatalogCollection::_NewEnum()方法。

让我们先做早绑定版本,因为你不太可能真的想做晚绑定。这个服务器已经稳定了很长一段时间,而且。net 4.0的嵌入互操作类型特性避免了对互操作库的依赖。使用项目>添加参考>浏览按钮>选择c:'windows'system32'com'comadmin.dll。示例代码:

static void EarlyBound(string server) {
    var cat = new COMAdmin.COMAdminCatalog();
    cat.Connect(server);
    var coll = (COMAdmin.COMAdminCatalogCollection)cat.GetCollection("Applications");
    coll.Populate();
    foreach (COMAdmin.ICatalogObject app in coll) {
        Console.WriteLine(app.Name);
        var comps = coll.GetCollection("Components", app.Key);
        comps.Populate();
        foreach (COMAdmin.ICatalogObject comp in comps) {
            Console.WriteLine("  {0} - {1}", comp.Name, comp.Key);
        }
    }
}

由于dynamic关键字,后期绑定版本没有太大的不同:

static void LateBound(string server) {
    var catt = Type.GetTypeFromProgID("COMAdmin.COMAdminCatalog");
    dynamic cat = Activator.CreateInstance(catt);
    cat.Connect(server);
    dynamic coll = cat.GetCollection("Applications");
    coll.Populate();
    foreach (dynamic app in coll) {
        Console.WriteLine(app.Name);
        dynamic comps = coll.GetCollection("Components", app.Key);
        comps.Populate();
        foreach (dynamic comp in comps) {
            Console.WriteLine("  {0} - {1}", comp.Name, comp.Key);
        }
    }
}

按照要求,这段代码的。net 2.0的最新绑定版本,是日内瓦程序员权利公约所禁止的残酷而不寻常的惩罚。从_NewEnum() COM方法获得迭代器,可以将其强制转换为IEnumerator:

static void LateBound20(string server) {
    Type catt = Type.GetTypeFromProgID("COMAdmin.COMAdminCatalog");
    object cat = Activator.CreateInstance(catt);
    cat.GetType().InvokeMember("Connect", BindingFlags.InvokeMethod, null,
        cat, new object[] { server });
    object coll = cat.GetType().InvokeMember("GetCollection", BindingFlags.InvokeMethod, null,
        cat, new object[] { "Applications" });
    coll.GetType().InvokeMember("Populate", BindingFlags.InvokeMethod, null,
        coll, new object[] { });
    object iter = coll.GetType().InvokeMember("_NewEnum", BindingFlags.InvokeMethod, null,
        coll, new object[] { });
    System.Collections.IEnumerator iter1 = (System.Collections.IEnumerator)iter;
    while (iter1.MoveNext()) {
        object app = iter1.Current;
        object name = app.GetType().InvokeMember("Name", BindingFlags.GetProperty, null,
            app, new object[] { });
        object key = app.GetType().InvokeMember("Key", BindingFlags.GetProperty, null,
            app, new object[] { });
        Console.WriteLine(name.ToString());
        object comps = coll.GetType().InvokeMember("GetCollection", BindingFlags.InvokeMethod, null,
            coll, new object[] { "Components", key });
        comps.GetType().InvokeMember("Populate", BindingFlags.InvokeMethod, null,
            comps, new object[] { });
        object iter2 = comps.GetType().InvokeMember("_NewEnum", BindingFlags.InvokeMethod, null,
            comps, new object[] { });
        System.Collections.IEnumerator iter3 = (System.Collections.IEnumerator)iter2;
        while (iter3.MoveNext()) {
            object comp = iter3.Current;
            object cname = comp.GetType().InvokeMember("Name", BindingFlags.GetProperty, null,
                comp, new object[] { });
            object ckey = comp.GetType().InvokeMember("Key", BindingFlags.GetProperty, null,
                comp, new object[] { });
            Console.WriteLine("  {0} - {1}", cname, ckey);
        }
    }
}

所有三个片段在我的COM+无妨碍机器上的输出:

COM+ Utilities
  RemoteHelper.RemoteHelper - {E423AF7C-FC2D-11D2-B126-00805FC73204}
  TxCTx.TransactionContext - {7999FC25-D3C6-11CF-ACAB-00A024A55AEF}
  TxCTx.TransactionContextEx - {5CB66670-D3D4-11CF-ACAB-00A024A55AEF}
  QC.Recorder - {ECABAFC2-7F19-11D2-978E-0000F8757E2A}
  QC.ListenerHelper - {ECABAFC4-7F19-11D2-978E-0000F8757E2A}
COM+ QC Dead Letter Queue Listener
  QC.DLQListener - {ECABAFCA-7F19-11D2-978E-0000F8757E2A}
COM+ Explorer
  COMEXPS.CTrkEvntListener - {2C3E140B-7A0D-42D1-B2AA-D343500A90CF}
COM+ Utilities (32 bit)
  RemoteHelper.RemoteHelper - {E423AF7C-FC2D-11D2-B126-00805FC73204}
  TxCTx.TransactionContext - {7999FC25-D3C6-11CF-ACAB-00A024A55AEF}
  TxCTx.TransactionContextEx - {5CB66670-D3D4-11CF-ACAB-00A024A55AEF}
  QC.Recorder - {ECABAFC2-7F19-11D2-978E-0000F8757E2A}
  QC.ListenerHelper - {ECABAFC4-7F19-11D2-978E-0000F8757E2A}
System Application
  Catsrv.CatalogServer - {182C40F0-32E4-11D0-818B-00A0C9231C29}
  EventPublisher.EventPublisher - {ECABAFBC-7F19-11D2-978E-0000F8757E2A}
  COMSVCS.TrackerServer - {ECABAFB9-7F19-11D2-978E-0000F8757E2A}
  Mts.MtsGrp - {4B2E958D-0393-11D1-B1AB-00AA00BA3258}
  Pdump.ProcessDump - {ECABB0C4-7F19-11D2-978E-0000F8757E2A}