Hallo,
Ich möchte Objekte zur Laufzeit Konvertieren. z.B. von Label zu
Button, oder Class1 zu Class2. Dabei sollen alle gleichen Member
(Felder, Propertys, usw) in einer Schleife übernommen werden. Das klappt
auch ganz gut. Allerdings komme ich bei den Events nicht mehr weiter,
und hänge bereits ca eine Woche an diesem Punkt fest.
Es sollen alle "registrierten und möglichen Events" der Class1 später
von der konvertierten Class2 aufgerufen werden können. Diese Events
(und alle anderen Member) sollen von "Außen" abgefragt werden
(Konvertierungs-Klasse), also nicht dort, wo die Class1 Instanz liegt.
Alle Member und Klassen, auch die Methoden sind Public. Müsste ja
eigentlich gehen!
Ich bekomme eine Liste der benutzen Delegaten (die Methoden der Events)
eines Objektes: ...
...Jedoch kann ich diese nicht mehr den Events zuordnen. Dort stehen
dann wirklich NUR die Delegaten/Methoden, und der
EventHandlerList.Key-Property ist immer leer!?? Mittlerweile ist es ein
ebiges hin und her mit diversen Snippets, und leider finde ich keinen
Weg.
Ich bräuchte als Result etwa so was:
1
-Object: Class1
2
-EventList:
3
-EventInfo Click, Delegate ClickHandlerMethod
4
-EventInfo MouseMove, Delegate MoveHandlerMethod
5
-EventInfo AbcEvent, Delegate AbcHandlerMethod,
...Also ich bräuchte einen Delegate oder MethodInfo passend zur
Eventinfo zur Laufzeit. Dann kann ich diese auf der Class2 anwenden
bzw. anmelden. Kann mir jemand weiterhelfen?
Gruß, tsx
Tim S. schrieb:> Ich bräuchte als Result etwa so was:> -Object: Class1> -EventList:> -EventInfo Click, Delegate ClickHandlerMethod> -EventInfo MouseMove, Delegate MoveHandlerMethod> -EventInfo AbcEvent, Delegate AbcHandlerMethod,
Meinst du etwas in dieser Richtung?
1
namespace Bla
2
{
3
class Foo
4
{
5
public event EventHandler EventW;
6
public event EventHandler EventX;
7
public event EventHandler EventY;
8
public event EventHandler EventZ;
9
10
public Foo()
11
{
12
EventW += Foo_x;
13
EventX += Foo_y;
14
}
15
16
public void Foo_x(object sender, EventArgs e) {}
17
public void Foo_y(object sender, EventArgs e) {}
18
}
19
20
class Program
21
{
22
static void Main(string[] args)
23
{
24
var foo = new Foo();
25
26
foo.EventY += MyHandler;
27
foo.EventZ += (s, e) => { };
28
29
var events = foo.GetType().GetEvents();
30
31
foreach (var ev in events)
32
{
33
FieldInfo fi = foo.GetType().GetField(ev.Name, BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo fi = foo.GetType().GetField(ev.Name, BindingFlags.NonPublic | BindingFlags.Instance);
2
Delegate del = (Delegate)fi.GetValue(foo);
Genau das habe ich auch mehrfach gefunden und getestet. FieldInfo fi ist
immer null.
Tim S. schrieb:> Diese Events und alle anderen Member sollen von "Außen" abgefragt werden
...also von einer Converter-Klasse! (ConvertFooBarBaz)
Eventuell geht das doch nicht!?
1
usingSystem;
2
usingSystem.Collections.Generic;
3
usingSystem.Linq;
4
usingSystem.Reflection;
5
usingSystem.Text;
6
usingSystem.Threading.Tasks;
7
namespaceBla
8
{
9
// Klassen, dessen Member-Inhalte zu "konvertieren" bzw zu übernehmen sind.
10
// Verschiedene Klassen, mit den selben Member-Namen und Typen (vererbt!)
11
// z.B bei allen Controls, Usercontrols: "BackColor".
Es ist kein "konvertieren" oder "mappen" im eigentlichen Sinne, sondern
lediglich das Übernehmen der einzelnen Werte auf ein anderes Objekt. Es
fehlen nur noch die Events. Hoffentlich ist verständlich was ich meine.
Habe das grob reduziert!
Bestimmt gibt es das auch schon irgendwo als Snippet im Netz? Ich finde
jedoch gar nichts. Wonach soll ich eigentlich suchen!?
Danke für die Hilfe! tsx
Ich habe versucht die Methode von Monomops zu verwenden
FieldInfo fi = foo.GetType().GetField(ev.Name, BindingFlags ...);
FieldInfo fi = foo.GetType().GetField("Event"+ ev.Name, BindingFlags ...
);
Was der Compiler an Feldern pro Event baut weiß ich noch nicht, und auch
nicht wie ich darauf zugreifen kann...
FeldInfos sind wie gesagt immer null!!
Ich habe versucht die Eventhandler mit Attributen zu finden.
z.B. Die Methode ClickHandler mit einem ClickHandlerAttribute schmücken.
Bringt aber nichts, gefällt mir nicht und schaff ich auch gar nicht
erst. Jede Funktion bräuchte eine eigene Attribute und das ist
Schwachsinn und viel zu statisch für das Projekt.
Ich überlege mir eine Art Liste aufzubauen, die darüber bescheid weiß,
welches Event zu welchen Delegaten und Handler gehört. Diese wird dann
zur Laufzeit erweitert oder verändert.
Tim S. schrieb:> Wonach soll ich eigentlich suchen!?
Event Publisher/Subscriber Pattern anscheinend.
Jedoch denke ich, dass es oben genannten Snippet schon fertig gibt, es
ist doch bestimmt wichtig mal Class1 nach Class2 zu "wandeln"!? Warum
gibt es das nicht!? Das braucht doch gefühlt jeder Mensch hunderte male
am Tag! Ohne scheiß! Muss man das mit jeden Member statisch einzeln
machen!? - Wäre doch ultra schwach von .Net
Hat jemand vielleicht noch einen Tipp???
tsx
Edit:
Frank L. schrieb:> Gruß> Frank
Danke, ich schau mal rein!
Mal davon abgesehen, dass es sich mir nicht erschließt, welchen Sinn es
macht, Felder von Label nach Button zu kopieren und dabei auch noch die
Event-Handler (Verweise auf Programm-Code!) kopieren zu wollen... Wobei
ich das natürlich nicht verstehen muss... ;-)
Schreibe doch mal ein kleines Test-Programm und schaue dir die erzeuge
Assembly mit ILDASM an. Das ist ein Tool des DotNet-Frameworks, in dem
Du den erzeugten IL-Code anschauen kannst. Dort wirst Du recht schnell
finden, welche "Felder" der C#-Compiler bei Events verwendet.
Grüße
Markus
Markus schrieb:> welchen Sinn es macht
Ich baue ein GUI und möchte grad Drag&Drop einbauen bzw vorbereiten. Ich
suche eine universelle Möglichkeit, um ein Element (z.B) vom TreeView in
ein Panel zu Draggen - oder von dort aus in ein ToolStrip, (etc...) und
möchte dessen Eigenschaften auf das neue Controll anwenden
(konvertieren), ohne alles Statisch machen zu müssen. Das funktioniert -
nur eben die Events noch nicht.
Markus schrieb:> schaue dir die erzeuge Assembly mit ILDASM an
Kann das mehr als Reflection zur Laufzeit? Meinst du das vom Win SDK?
(Lade ich grad runter)
Tim S. schrieb:> Ich baue ein GUI und möchte grad Drag&Drop einbauen bzw vorbereiten. Ich> suche eine universelle Möglichkeit, um ein Element (z.B) vom TreeView in> ein Panel zu Draggen - oder von dort aus in ein ToolStrip, (etc...) und> möchte dessen Eigenschaften auf das neue Controll anwenden> (konvertieren), ohne alles Statisch machen zu müssen. Das funktioniert -> nur eben die Events noch nicht.
Das ist doch ausgekochter Schwachsinn hoch drei. Drag&Drop: OK. Elemente
zwischen verschiedenen "Containern" transferieren: auch OK.
Der Punkt ist aber: die Tatsache, dass "Elemente" zwischen verschiedenen
"Containern" hin und her transferiert werden, ändert erstmal rein garnix
an den transferierten Elementen selber, weder an deren Inhalt noch an
deren Typ (also deren Klasse). Und das muss es auch nicht, denn alles,
was sich tatsächlich ändert, ist ja die Position im Container oder
maximal der Container selber.
Dein Problem kann also allenfalls sein, die Elemente an die Ereignisse
des neuen Containers zu koppeln.
Kannst du dass mal langsam im Rahmen deiner intellektuellen
Möglichkeiten durchdenken und dann ggf. bestätigen?
Weil: wenn die Antwort "ja" ist, könnte man der Lösung deines Problems
doch schon sehr viel näher kommen...
c-hater schrieb:> Das ist doch ausgekochter Schwachsinn hoch drei. Drag&Drop: OK. Elemente> zwischen verschiedenen "Containern" transferieren: auch OK.>> Der Punkt ist aber: die Tatsache, dass "Elemente" zwischen verschiedenen> "Containern" hin und her transferiert werden, ändert erstmal rein garnix> an den transferierten Elementen selber, weder an deren Inhalt noch an> deren Typ (also deren Klasse). Und das muss es auch nicht, denn alles,> was sich tatsächlich ändert, ist ja die Position im Container oder> maximal der Container selber.>> Dein Problem kann also allenfalls sein, die Elemente an die Ereignisse> des neuen Containers zu koppeln.>> Kannst du dass mal langsam im Rahmen deiner intellektuellen> Möglichkeiten durchdenken und dann ggf. bestätigen?>> Weil: wenn die Antwort "ja" ist, könnte man der Lösung deines Problems> doch schon sehr viel näher kommen...
Und Deine Antwort ist an Schwachsinn nicht zu übertreffen. Denk mal
weiter als Dein Tellerrand, dann fallen Dir wahrscheinlich mehr als ein
paar Dinge ein, bei denen ein Button auf einmal ein MenueItem sein
könnte oder sonstiges...
Gruß
Frank
Frank L. schrieb:> Hallo Tim,> und hier die verkürzte Version ohne foreach Schleife.
Joaa genau das brauche ich. Hatte ich zuvor auch schon mehrfach
gefunden, jedoch funktionierte das nicht wirklich... Das jetzt läuft
schon besser, und bringt mich erstmal weiter... Dankeschön
Tim S. schrieb:> Ich habe versucht die Methode von Monomops zu verwenden
Auch diese FieldInfo f1 ist hier null, aber anscheinend braucht die eh
niemand! :-) LOOL
Tim S. schrieb:> Mittlerweile ist es ein ebiges hin und her mit diversen Snippets
Wie oft ich zuvor beim Debuggen dieser vielen Online-Fetzen abgebrochen
habe, nur weil diese fi null ist ... AHHRRG! - den ganzen Part danach
habe ich nicht mehr debuggt oder getestet. Dabei hatte es anscheinend
schon ansatzweise funktioniert. Jedoch fehlte mir folgende Zeile:
Frank L. schrieb:
1
list2.AddHandlers(list);
Das löst eigentlich alle Probleme mit einem Schlag! Ich hatte zuvor die
EventHandlerList in irgendwelche Dictionarys gewandelt, um an die
Delegaten / MethodInfos zu kommen, und die Events dann alle "manuell"
dort anzumelden. Deine Zeile macht das alles von alleine! ;-)
c-hater schrieb:> Weil: wenn die Antwort "ja" ist, könnte man der Lösung deines Problems> doch schon sehr viel näher kommen...Frank L. schrieb:> ...dann fallen Dir wahrscheinlich mehr als ein> paar Dinge ein, bei denen ein Button auf einmal ein MenueItem sein> könnte oder sonstiges...
Joaa genau das habe ich gemeint!
Ich stelle mein Code dann hier rein wenn er fitt geworden ist.
Danke an alle und dir Frank!
tsx