2015-09-25 5 views
0

Мне нужно перебирать объекты коллекции COM +/ActiveX, используя поздний bind interop в C#. В этот момент мне нужно итерации COMAdmin.COMAdminCatalogCollection, от GetCollection("Applications") метода в COMAdmin.COMAdminCatalog. Но поскольку это POC для использования с другими собственными объектами COM +/ActiveX, мне нужно сделать это с помощью поздней привязки. Как я должен помещать мой объект object в истребитель?Объект коллекции Iterate ActiveX с поздним связующим взаимодействием на C# (COMAdminCatalogCollection)

COMPlus.cs
public abstract class COMPlus 
{ 
    public object COMObject { get; private set; } 
    public System.Type COMObjectType { get; private set; } 

    protected COMPlus(string progId) 
    { 
     this.COMObject = System.Activator.CreateInstance(System.Type.GetTypeFromProgID(progId)); 
     this.COMObjectType = this.COMObject.GetType(); 
    } 

    protected COMPlus(object comObject, string progId) 
    { 
     this.COMObject = comObject; 
     this.COMObjectType = System.Type.GetTypeFromProgID(progId); 
    } 
} 

COMAdminCatalog.cs
public class COMAdminCatalog : COMPlus 
{ 
    public COMAdminCatalog() : base("COMAdmin.COMAdminCatalog") { } 
    public COMAdminCatalog(object comObject) : base(comObject, "COMAdmin.COMAdminCatalog") { } 

    public void Connect(string serverAddress) 
    { 

    } 

    public COMAdminCatalogCollection GetCollection(string collectionName) 
    { 
     return new COMAdminCatalogCollection(
      base.COMObjectType.InvokeMember("GetCollection", 
       System.Reflection.BindingFlags.InvokeMethod, 
       null, 
       base.COMObject, 
       new object[] { (object)collectionName })); 
    } 
} 

COMAdminCatalogCollection.cs

public class COMAdminCatalogCollection : COMPlus 
{ 
    public COMAdminCatalogCollection() : base("COMAdmin.COMAdminCatalog") { } 
    public COMAdminCatalogCollection(object comObject) : base(comObject, "COMAdmin.COMAdminCatalog") { } 

    public void Populate() 
    { 
     base.COMObjectType.InvokeMember("Populate", 
      System.Reflection.BindingFlags.InvokeMethod, 
      null, 
      base.COMObject, null); 
    } 
} 

Toolbox.cs

public static class Toolbox 
{ 
    public static void CreateApp(string appName, string serverAddress = null) 
    { 
     COMAdminCatalog comAdminCatalog = new Interop.COMAdmin.COMAdminCatalog(); 
     COMAdminCatalogCollection comAdminCatalogCollection; 

     if (!String.IsNullOrEmpty(serverAddress)) 
     { 
      comAdminCatalog.Connect(serverAddress); 
     } 

     comAdminCatalogCollection = comAdminCatalog.GetCollection("Applications"); 

     comAdminCatalogCollection.Populate(); 

     // here the fun has to begin iterating the Applications collection to verify if there is already an application with the given name or not. 
    } 
} 

EDIT

Мне это нужно для совместимости с .Net 2.0 (3.5 tops), поэтому динамика мне не подходит.

ответ

2

Вы используете ключевое слово foreach на C#, как обычно, чтобы перебирать коллекцию. DLR знает, как автоматически сопоставить его с методом ICatalogCollection::_NewEnum().

Давайте сначала сделаем раннюю версию, так как очень маловероятно, что вы действительно хотите сделать это на поздней основе. Этот сервер был стабильным в течение очень долгого времени, а функция .NET Embed Interop Types позволяет избежать зависимости от библиотеки interop. Используйте Project> Добавить ссылку> Обзор> выберите 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} 
+0

К сожалению, я не сказал Мне нужно, чтобы он совместим с .Net 2.0 (3.5 tops), поэтому динамика мне не подходит. Просто отредактировал вопрос, чтобы добавить этот реквизит. – MFedatto

+0

Вздох, хорошая работа. Теперь вы * определенно * любите раннюю версию. –

+0

>. <Мне нужно решение с поздним сроком действия, потому что у нас в компании много COM + и растущий спрос на веб-сервисы, демонстрирующие эти решения, используя совершенно новый канонический подход. Я использую COMAdminCatalog просто как POC. – MFedatto