Est-il possible pour une classe native de consommer un événement .NET?
Question
Avez-vous une idée de la façon d'initialiser un délégué .NET qui pointe vers une méthode à partir d'une instance de classe "mixte"?
J'ai une classe C ++ 'mixte' comme ceci:
class CppMixClass
{
public:
CppMixClass(void){
dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(&UpdateHealthState);
}
~CppMixClass(void);
void UpdateState(System::Object^ sender, DotNetClass::StateEventArgs^ e){
//doSmth
}
}
DotNetClass est implémenté en C # et la déclaration de méthode est OK avec délégué. Cette ligne génère une erreur:
dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(&UpdateHealthState);
error C2276: '&' : illegal operation on bound member function expression
Quelqu'un a-t-il la moindre idée d'un problème? Peut-être que coz CppMixClass class n’est pas une pure classe .NET (ref)?
Cela a fonctionné quand UpdateHealthState est une méthode statique, mais j'ai besoin d'un pointeur sur la méthode d'instance.
J'ai essayé par exemple:
dotNETclass->StateChanged += gcnew DotNetClass::ServiceStateEventHandler(this, &UpdateHealthState);
Mais cela ne fonctionne évidemment pas car ce n'est pas un pointeur (handle) vers la classe .NET (ref), (System :: Object).
ServiceStateEventHandler est défini en C # comme suit:
public delegate void ServiceStateEventHandler(object sender, ServiceStateEventArgs e);
Merci d'avoir lu ceci:)
La solution
Je viens de trouver une réponse à cette question (bien sûr, par Nishant Sivakumar, l’homme semble avoir des réponses à tous mes problèmes liés à l’interopérabilité C ++ / CLI):
http://www.codeproject.com/KB/mcpp /CppCliSupportLib.aspx?display=Print
La réponse est située dans "msclr / event.h". en-tête, où sont définies les macros des délégués dans les classes natives.
Le code de Nish est le suivant:
class Demo5
{
msclr::auto_gcroot<FileSystemWatcher^> m_fsw;
public:
// Step (1)
// Declare the delegate map where you map
// native method to specific event handlers
BEGIN_DELEGATE_MAP(Demo5)
EVENT_DELEGATE_ENTRY(OnRenamed, Object^, RenamedEventArgs^)
END_DELEGATE_MAP()
Demo5()
{
m_fsw = gcnew FileSystemWatcher("d:\\tmp");
// Step (2)
// Setup event handlers using MAKE_DELEGATE
m_fsw->Renamed += MAKE_DELEGATE(RenamedEventHandler, OnRenamed);
m_fsw->EnableRaisingEvents = true;
}
// Step (3)
// Implement the event handler method
void OnRenamed(Object^, RenamedEventArgs^ e)
{
Console::WriteLine("{0} -> {1}",e->OldName, e->Name);
}
};
Autres conseils
Seuls les types .NET peuvent utiliser des événements. Je suggère de créer une nouvelle classe gérée qui gère l'événement et compose cette classe dans CppMixClass, puis passe un pointeur à CppMixClass lors de la construction. Votre classe de gestion des événements gérés peut ensuite appeler une fonction sur CppMixClass lorsqu'elle gère un événement.