Verzwickt - Methode an Methode übergeben
-
(Datei a.h) ref class a { delegate void mdel(String^ Test); a() { mdel^ mydel = gcnew mdel(/* hier fangen die Probleme an */); }; m(Typ^ Methode) {}; }; (Datei b.h) ref class b { b(); { a^ A = gcnew a(b::Methode); }; void Methode(String^ bla) {}; // Methode darf nicht statisch sein };
Hallo Jochen
Also hätte ich in Klasse a dann ungefähr so etwas:
delegate void mdel(String^ Test);
Und im Konstruktor dann:
mdel^ mydel = gcnew mdel(/* hier fangen die Probleme an */);
Denn der Delegat muss ja mit (Klasse, Methode bzw. Pattern) instantiiert werden. Also es genügt nicht, ihn einfach nur zu definieren, richtig?
mdel() verlangt ja dann etwas, wie die instantiierte Klasse und die Methode. Erstere kann ich aber nicht in die Definition schreiben, richtig?Das ist das logische Problem, das ich damit habe und ich weiss nicht, wie ich das lösen kann.
-
Ich verstehe Dein Problem nicht ganz... was willst Du denn genau machen?
-
Ich habe hier diese Klasse:
ref class AppEvents { public: AppEvents(AppEvent^ NewEvent); AppEvents(AppEvent^ NewEvent, /* Typ? */ HandlerMethode); void HandleEvent(Object^ Sender, AppEventArgs^ e); };
Und dieser will ich eben auch die das Event behandelnde Methode übergeben, damit dann durch diese Klasse der entsprechende EventHandler erzeugt wird. So ist das eben schön aufgeräumt und alles in einer Klasse (nagut - sind noch mehr Klassen, aber der Code sollte dort hinein).
Also müsste auch dort der Delegate hinein, denn es sollte möglichst nicht noch zusätzlicher Code irgendwo im Programm stehen, der eigentlich mit der Klasse hier zu tun hat. Ich hatte das dann eben so versucht, dass ich den Delegaten im Konstruktor erzeugt habe (und sonst eben nichts) und dann eine Methode anstelle des Konstruktors für die Erzeugung des Events und Übergabe der behandelnden Methode geschrieben habe (aber beim Delegaten war's dann vorbei quasi). Ich dachte mir schon, dass es so gehen muss, nur habe ich eben das Problem mit den Parametern für den Delegaten.
-
Was soll den "HandlerMethode" sein? Das muss doch von aussen kommen, oder?
Und damit es typsicher ist (was .NET ist), musst Du den delaget definieren, der dann auch aussen sichtbar ist und übergeben werden muss.
-
So - musste leider schnell weg.
Also mit Handler Methode meine ich das hier z.B.:
Application::ApplicationExit += gcnew EventHandler(this, &AppCon::OnApplicationExit); System::Void OnApplicationExit(System::Object^ sender, EventArgs^ e);
OnApplicationExit ist hier die Methode, die aufgerufen wird, wenn das Event ausgelöst wird. Und die wird ja auch bei Registrierung des Events übergeben.
musst Du den delaget definieren, der dann auch aussen sichtbar ist und übergeben werden muss.
Nach aussen kann aber auch innerhalb der Klasse sein, oder nicht? Denn letztendlich wird ja die Methode - z.B. irgendeineKlasse::OnApplicationExit an eine Methode in der Klasse übergeben und somit muss ja nur innerhalb der Klasse der Delegat bekannt sein (also hoffe ich).
Also dachte ich mir eben, den Delegaten zu definieren und zu instantiieren (innerhalb der Klasse) sollte reichen. Mein Problem ist eben nur:
[/cpp]DelInst += gcnew MyDel(a, &A::func2);Also MyDel will hier ja eine instantiierte Klasse (a) und die Referenz zu einer Methode innerhalb der definierten Klasse, soweit ich das verstanden habe. Ich frage mich nur, wie ich das übergeben soll, denn es werden 2 Parameter erwartet und ich würde natürlich gerne nur &A::func2 übergeben wollen.
MyDel ^ StaticDelInst = gcnew MyDel(&A::func3);[cpp]
So wäre das bei einer statischen Methode. Richtige Übergabe aber leider ist die Methode nicht immer statisch (solch eine Handler Methode könnte wohl statisch sein, aber nicht statisch wäre besser).Ich weiss, klingt konfuss Ich hatte gehofft, mit dem ersten Beispiel gleich alles erklärt zu haben Vielleicht denke ich da einfach zu kompliziert.
-
Ach so... Du musst einen *Event* definieren!... dann musst Du nix übergeben.. oder was meinst Du!?
-
Ja fast
Also der Event ist schon fertig (fast) definiert.
Mit diesem KonstruktorAppEvents(AppEvent^ NewEvent);
wird mittels
NewEvent->Event += gcnew AppEvent::AppEventHandler(this, &AppEvents::HandleEvent);
wie gehabt in dem Falle
void HandleEvent(Object^ Sender, AppEventArgs^ e);
als HandlerMethode (also die Methode, die eben das auftretende Event bearbeitet) übergeben.
Aber ich bräuchte eben noch (also bräuchte... es wäre eben schön, damit diese Klasse nun auch wirklich in sich stimmig und wiederverwendbar ist) etwas, wie:
AppEvents(AppEvent^ NewEvent, /* Typ? */ HandlerMethode);
Über diesen Konstruktor soll dann eben wahlweise eine andere Methode aus einer anderen Klasse übergeben werden können, um diese dann als das Event behandelnde Methode zu initialisieren.
Und dabei habe ich eben das Problem. Wie schreibe ich diese Übergabe. Delegat innerhalb der Klasse definieren und auch initialisieren geht ja, aber die zwei Parameter sind mein Problem. Und eine andere Frage ist eben noch die Typangabe bei der Übergabe der Methode, denn ich kann da ja nicht einfach eine feste Klasse angeben, da die Methode ja offen sein soll. Aber wenn ich z.B. Object^ verwende, dann gibt das nur eine Fehlermeldung.Es tut mir leid, wenn ich mich da nicht richtig erklären konnte, aber *g* ich hoffe, ich bringe Fragen bald besser auf den Punkt
-
Ich verstehe Dich nicht... Für was brauchst Du denn die AppEvent-Klasse!? Kann den Sinn (und somit auch Dein Problem) überhaupt nicht begreifen... sorry...
-
Diese Event-Klasse hat nichts mit irgend einem Form zu tun. Da (und in einer anderen Klasse) ist alles, was man braucht, um ein Event zu erstellen. Das ist doch der Sinn (also irgendwie) von Klassen.
Ohne so eine Klasse wären verschiedene Zeilen Code über teilweise mehrere Dateien verteilt (überall, wo ein solches Event gebraucht wird).Aber mal anders herum.
Ich habe... void Meth(Object^ SomeMeth); { MyDelegate += gcnew MyDel(Typ_der_Klasse_in_der_Meth_steckt, SomeMeth); }; ... void Hmeth(Object^ sender, EventArgs^ e);
Ich will nun Hmeth an Meth übergeben, damit MyDelegate als Delegate für eben diesen Typ und diese Methode Meth initialisiert wird.
Sieht komisch aus, muss nun auch vom Sinn her nicht richtig sein, das Problem ist einfach nur:
Referenz einer Klasse::Methode via eines Methodenaufrufs Methode(Methodenreferenz) an einen Delegaten MyDel(Klasse_Typ, &Methode) zu übergeben. Wie kann ich das machen, wenn weder Methode noch Delegat statisch sind/sein werden?
-
ALso ich gebs auf...
Du *musst* das delegate von extern übergeben... da führt halt nun mal kein Weg dran vorbei...
-
Schade. Auch Reflektion könnte da nicht helfen? Na was soll's. Ich danke Dir für Deine Geduld.
-
Mit Reflection und Runtime-Activation kannst Du jeden schei** machen... aber das ganze soll doch ein wenig Typsicher sein, oder?
-
Ja, darum hätte ich gehofft, dass es da etwas gibt, das ich übersehen hatte. Aber wir hatten wohl auch ein bisschen an einander vorbei geredet. Ich hatte auch einfach nicht verstanden, dass ein Delegat wohl "hart" erstellt werden musss. Und später kam mir dann, dass ich den Wald vor lauter Bäumen nicht gesehen hatte *g* Es sollte doch möglich sein, den Code, wie gehabt, zu lassen... nur eben anstelle einer festen HandleEvent Methode in der Klasse eine Referenz auf eine Methode zu halten, die dann vor Erstellung des Delegaten einfach mit der gewünschten Methode verbunden wird. Hab's noch nicht getestet, aber das sollte wohl funktionieren und ist dann eigentlich das, was ich will. Nur eben anders.
Manchmal versucht man, einen Weg zu gehen... und merkt nicht, dass es auch einen anderen, vielleicht sogar besseren gibt
Danke Dir auf jeden Fall für Deine Geduld mit mir
-
Macan schrieb:
nur eben anstelle einer festen HandleEvent Methode in der Klasse eine Referenz auf eine Methode zu halten, die dann vor Erstellung des Delegaten einfach mit der gewünschten Methode verbunden wird.
Und das musst Du doch auch hart-reincode, oder wie stellst Du Dir das vor???
Aus diesem Grunde verstehe ich nicht warum Du kein Delegate verwenden kannst/willst.
-
Können und wollen natürlich schon. Ich hätte den nur gerne innerhalb der Klasse gehabt. Aber das geht nicht und ich hab's verstanden. Mit "hart" meine ich, dass natürlich im Code die Definition eines Delegaten stehen muss (und Instantiierung, Zuweisung). Ich hätte eben nur gehofft, dass man da auch noch ein bisschen Dynamik hinein bringen hätte können. Also eben den Zuweisungsteil im Delegaten auch durch eine Variable darstellen hätte können.
Das mit der Referenz, von der ich sprach, läuft ja auch wieder auf einen Delegaten hinaus - also geht's nicht so. Das ist für mich ja nur eine Übung, was geht und was nicht. Du musst verzeihen, aber ich komme eben von c und bin eigentlich nach kürzester c++ Phase gleich in .net eingestiegen. Da hakelt es immer noch leicht *g*
EDIT: Ich will einfach nur wissen, wie weit man gehen kann und wie dynamisch man einiges gestalten kann.
-
Mit Refelction und Activator / DynamicInvoke kann man sehr weit gehen... aber ich rate davon ab, da hier die ganzen Überprüfungen vom Compiler wegfallen...
Schau Dir halt mal den "System::Reflection" namespace an. Da kannst Du Klassen erzeugen / Methoden / Properties aufrufen wie Du willst (sogar welche die als "private" deklariert sind).
-
Das klingt fast schon beängstigend. Aber ich glaube, davon lasse ich (noch) zumindest die Finger. Denn ich sollte wirklich erstmal ein tiefes Verständnis von .net haben und einen, sagen wir mal, sicheren Stil. Zu leicht gewöhne ich mir dann wieder an, einige Konstrukte zu umgehen.
Aber danke für den Tip - ich werd's früher oder später schon brauchen