Am incercat de curand sa apelez niste metode si sa citesc niste atribute dintr-un COM library cu reflection.
Ideea e ca vreau sa fac subscribe la niste evenimente si nu mi-a iesit.
A luat cam aiurea codul:
Ideea e urmatoarea: eventul de operationComplete arunca Object result. Si eu am nevoie de acel result.
Si operationcomplete se triggeruieste dupe apelul functiei Operate().
//Aduc tipul din active x
var COMtype = Type.GetTypeFromCLSID(Guid.Parse(CLSID.objcode), true);
//Instantiez obiectul
object COMobj = Activator.CreateInstance(COMtype);
//Apelez metoda de init
COMtype.InvokeMember(“Init”, BindingFlags.InvokeMethod, null, COMobj, null);
Ca sa fac un handler vad ca trebuie sa aduc eventul urmarit din com class, numai ca daca ii dau asa:
EventInfo ei = COMtype.GetEvent(“OperationComplete”);
OK, problema e clasica pentru interoperabilitate cu COM.
Solutia este clasa statica ComEventsHelper, cu cele doua metode ale sale, Combine (adauga event handler) si Remove (sterge event handler). Sper ca, folosind aceasta informatie, te descurci mai departe.
Motivul pentru care nu functioneaza Reflection cum ai vrea tu este ca obiectele COM nu sunt obiecte standard .NET. Ceea ce vezi tu ca si event handling este mai mult eye-candy pentru developeri, insa, in spate, lucrurile nu functioneaza in acest fel. Compilatorul face multe modificari, si, drept rezultat, ceea ce tie la compile time iti functioneaza, nu iti va mai exista la run-time, prin urmare Reflection nu le va mai vedea.
Ca regula generala, incearca sa eviti late binding catre obiecte COM if you can avoid it. Clasele wrapper pe care .NET le genereaza automat sunt acolo cu un scop.
Multumesc pentru raspuns.
M-am uitat la functia mentionata de tine si nu prea inteleg cum sa fac legaturile.
public static void Combine (object rcw, Guid iid, int dispid, Delegate d);
rcw - este target object, adica COMobject
Guid - il am din Guid.Parse
dispid - este
Si nu stiu cum sa leg de eventul “operationComplete”.
Daca ma poti indruma ar fi perfect.
Clasele wrapper sunt cele apar direct in COM, cand adaug o referinta?
var method = Type.GetType(“test.Program”).GetMethod(“kxc_operationComplete”);
var tArgs = new List();
foreach(var param in method.GetParameters())
tArgs.Add(param.ParameterType);
tArgs.Add(method.ReturnType);
var delDeclType = Expression.GetDelegateType(tArgs.ToArray);
Delegate d = Delegate.CreateDelegate(delDeclType, method);
ComEventsHelper.Combine(COMobj, guid, 1, d);
Si la combine bubuie.
Apropos de ComEventsHelper: nu stiu de unde ai gasit clasa asta, ca nu cred ca multa lume din univers stie de ea.
Sau, daca nu realizeaza ce tip implicit de delegate sa foloseasca, mai degraba:
ComEventsHelper.Combine(COMobj, guid, 1, new Action<Object>(kxc_operationComplete)); ?
Tu ai facut urmatoarele in codul tau: ai analizat tipul in care te afli, ai luat MethodInfo pentru kxc_operationComplete, ai adaugat atat parametri cat si return type-ul intr-o lista, dupa care ai cerut sa ti se dea un Func cu argumentele acelea, din care ti-ai obtinut o instanta de delegate static, pe care ai trimis-o mai departe.
Nu imi dau seama cum arata obiectele doar din ce ai scris aici, asa ca nu imi dau seama daca e bine, dar sunt tentat sa cred ca nu. In orice caz, cu siguranta e un mod foarte neoptim de a scrie.
Asa este. Si nul dintre telurile mele in viata este ca sa existe cat mai putini care sa fie nevoiti sa auda de ea. Tu, ca si mine, ai fost ghinionist, insa poti propovadui si tu mai departe programatorilor tineri sa nu se atinga de nimic ce contine “COM” daca pot sa rezolve altfel Glumesc, evident, insa COM chiar nu e un lucru usor.
So, exceptia este buna, asta inseamna ca ai reusit sa faci legatura, si si sa chemi ceva din COM.
Partea proasta este ca, din acest moment, you are on your own, in sensul ca trebuie sa te asiguri ca ceea ce chemi tu actually poate executa. HRESULT-ul pe care il ai indica o problema in codul executat din COM, sau o problema de inregistrare.
Event system-ul din COM este foarte asemanator cu conceptul de duplex RPC channel. Explicatia sistemului este foarte laborioasa, asa ca mai degraba te invit sa citesti mai multe la acest link.
Ca o explicatie scurta, .NET implementeaza obiecte numite “event sinks”, care, in spate, functioneaza ca si echivalentul lor in C++. Acestea sunt urmarite de CLR si, gratie clasei pe care ti-am dat-o, te poti atasa la evenimentele lor. Practic, clasa functioneazsa ca un wrapper .NET peste ce ar trebui sa faci in C++ ca sa consumi evenimente COM.
Cateva sfaturi legat de ce poti face mai departe:
Incearca sa prinzi exceptia cu un debugger (Visual Studio?) atasat. De regula, proprietatea InnerException iti poate da mai multe detalii. Daca aceasta este null, atunci cel putin poti vedea ce help link are si poate vezi mai departe; de asemenea, verifica intotdeauna stack trace-ul, poate exceptia vine dintr-un loc in care nu te astepti.
Odata ce stii ce interfata este apelata, incearca sa o apelezi manual ca si cum ar fi singura viaranta (cu wrapper, exact ca in codul care l-ai dat ca exemplu). Daca primesti acelasi tip de exceptie, atunci stii ca tu ti-ai facut treaba.