2012-01-31 10 views
8

Sto lavorando a un'applicazione che incorpora Mono e mi piacerebbe generare un evento dal livello C++ nel livello C#. Ecco cosa ho:Mono incorporato: come si genera un evento in C++?

void* itr(NULL); 
MonoEvent* monoEvent; 
while(monoEvent= mono_class_get_events(klass, &itr)) 
{ 
    if(0 == strcmp(eventName, mono_event_get_name(monoEvent))) 
     raiseMethod = mono_event_get_raise_method(monoEvent); 
} 

Tuttavia, raiseMethod torna sempre come NULL. Osservando la struttura del MonoEvent, sembra che siano stati popolati i metodi add e remove, ma non il raise? C'è qualcosa di speciale che devo fare per farlo funzionare?

MODIFICA: Se è importante, ecco la forma (di base) del delegato, della classe e degli eventi che sto usando nel livello C#.

public delegate void MyHandler(uint id); 
public class SimpleComponent : NativeComponent 
{ 
    public event MyHandler OnEnter; 
    public event MyHandler OnExit; 
} 

risposta

5

L'evento può essere definito nella classe padre? Se quindi è necessario attraversare la gerarchia di classe con qualcosa come il seguente:

MonoEvent* monoEvent; 
while (klass) 
{ 
    void* itr = NULL; 
    while(monoEvent= mono_class_get_events(klass, &itr)) 
    { 
     if(0 == strcmp(eventName, mono_event_get_name(monoEvent))) 
     raiseMethod = mono_event_get_raise_method(monoEvent); 
    } 
    klass = mono_class_get_parent(klass); 
} 

EDIT dopo il commento e rileggendo domanda:

E 'normale che il metodo rilancio per l'evento è NULL.

Questo metodo di solito restituisce null per eventi dichiarati con la parola chiave evento C# o la parola chiave evento Visual Basic. Questo perché i compilatori C# e Visual Basic non generano tale metodo per impostazione predefinita.

(source)

ho paura che può essere difficile da generare un evento di una classe. Perché in realtà sta infrangendo il concetto di eventi in .NET - il che dice che la classe stessa può solo attivare il proprio Evento. In realtà, anche da C# è difficile sollevare l'evento di un'altra classe.

Concettualmente, gli eventi sono una coppia di metodi add_handler e remove_handler in cui si specificano i delegati da chiamare quando si verificano le circostanze dell'evento. Spetta alla classe come implementa gli eventi. Tecnicamente, è solo un campo delegato privato, AFAIK. Puoi provare a localizzarlo.

Non sono sicuro che sia un approccio corretto, ma una delle risposte in How do I raise an event via reflection in .NET/C#? descrive come aumentare l'evento utilizzando la riflessione. Potresti provare a convertirlo in chiamate mono_class/mono_field, ecc.

+0

Nope. Attraverso il debug ho verificato che sto recuperando l'evento correttamente. Solo mono_event_get_raise_method restituisce null. get_add_method e get_remove_method valori di ritorno. – Jeff

+0

@Jeff ha aggiornato la mia risposta – Krizz

3

La risposta di Krizz è la più completa. Questo è il modo in cui ho risolto il mio codice per funzionare come mi aspetterei.

ho cambiato il # lato C:

public delegate void MyHandler(uint aEntityId); 
public class SimpleComponent: NativeComponent 
{ 
    public event MyHandler OnEnter; 
    public event MyHandler OnExit; 

    protected void CallOnEnter(uint aEntityId) 
    { 
     if (OnEnter != null) 
      OnEnter(aEntityId); 
    } 

    protected void CallOnExit(uint aEntityId) 
    { 
     if (OnExit!= null) 
      OnExit(aEntityId); 
    } 
} 

poi afferrò il metodo mono con

raiseMethod = mono_class_get_method_from_name(klass, "CallOnEnter", 1); 
+0

Bah, bastonatemi. Questa è praticamente la convenzione in .NET comunque. Il documento sugli eventi lo usa ([Raising an Event] (http://msdn.microsoft.com/en-us/library/wkzf914z.aspx) e il relativo [How To] (http://msdn.microsoft.com /en-us/library/9aackb16.aspx)), ed è utilizzato anche in tutte le classi del framework.Minori a parte: le convenzioni di denominazione renderebbero 'Entering' e' Exiting' i nomi "corretti" per i campi evento e 'OnEntering()'/'OnExiting' dovrebbe essere usato per i metodi che li generano. – millimoose

Problemi correlati