Autor |
Beitrag |
paul.-b
      
Beiträge: 26
|
Verfasst: Mo 14.12.09 09:59
Hallo zusammen,
Ich möchte Objekte unterschiedlicher klasse übergeben, die aber alle die gleiche Methode besitzen (gleicher name, Parameter und rückgabewert aber versch. Implementierung)
Jetzt möchte ich diese Methode Aufrufen. Wie kann ich die Objekte "generisch" in einer Methode übergeben und diese gemeinsame Funktion dann aufrufen (egal welcher typ kommt)
Und nein, die Klassen erben von keiner gemeinsamen Klasse. Den Code kann ich übrigens auch nicht umschreiben, weil ich ihn nich besitze.
Dank und Gruß
Paul
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 14.12.09 11:36
Hallo Paul,
das spricht für ein Interface: Das definiert die Methode als Deklaration; jede Klasse bindet das Interface ein und definiert die Methode so, wie sie es braucht. Der "einheitliche" Aufruf erfolgt dann ungefähr so:
C#-Quelltext 1: 2:
| IMyMethod item = myClassInstance as IMyMethod; item.MyMethod(); |
In der Praxis wird es natürlich etwas komplexer, aber vom Grundsatz geht es so.
Gruß Jürgen
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Mo 14.12.09 12:32
Ich weiß nicht ob ich das richtig verstanden habe.
Meine Klassen können generell kein interface erben, da ich den Code nicht besizte.
Ich glaube aber du meinst es anders...
Ist dann "myClassInstance" ein generischer typ? Weil bei mir sind die KLassen komplett verschieden und haben nur eine Methodendeklaration gleich.
thx
|
|
JüTho
      
Beiträge: 2021
Erhaltene Danke: 6
Win XP Prof
C# 2.0 (#D für NET 2.0, dazu Firebird); früher Delphi 5 und Delphi 2005 Pro
|
Verfasst: Mo 14.12.09 13:30
paul.-b hat folgendes geschrieben : | Ich weiß nicht ob ich das richtig verstanden habe.
Meine Klassen können generell kein interface erben, da ich den Code nicht besizte. |
Dann habe ich dich falsch verstanden. Der Begriff "Meine Klassen" ließ mich vermuten, dass du Einfluss auf die Definition hast.
paul.-b hat folgendes geschrieben : | Ich glaube aber du meinst es anders...
Ist dann "myClassInstance" ein generischer typ? |
Nein, es ist kein Typ, sondern es ist das, was der Name sagt: Mit kleinem Anfangsbuchstaben ist es eine Variable, und zwar eine Instanz (also ein konkretes Objekt) vom Typ MyClass, also einer bestimmten Klasse.
Unter diesen Umständen gibt es höchstens eine Lösung: Leite von jeder der gegebenen Klassen eine (eigene) Klasse ab, die das Interface benutzt. Ob es allerdings mit der schon vorhandenen Methode funktioniert, kann ich nicht sagen.
Gruß Jürgen
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Mo 14.12.09 14:47
hmm, dann hätte ich aber mein Ziel verfehlt, wenn ich jede ableiten würde. Dann kann ich die auch für jeden typ meine Funktion überladen und die Gemeinsame Methode dort aufrufen.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 14.12.09 14:55
Was soll das denn für eine Methode sein die alle Klassen haben aber weder von einem gemeinsamen Vorfahren kommt noch aus einem Interface?
Und wenn dem so ist wer programmiert so was?
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 14.12.09 15:45
Hallo!
Ich denke, Du hast noch die Wahl, es mit Reflection zu machen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| public void CallMethod(object o) { var t = o.GetType(); var m = t.GetMethod("MyMethod"); if (m != null) m.Invoke(o, null); } |
Das wäre für eine Methode "MyMethod", die keine Parameter. Es gibt von GetMethod aber auch eine Überladung, welche Methoden mit bestimmten Parametern findet.
Grüße
Christian
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 14.12.09 15:51
@Christian: Den Ratschlag hätte ich gerne explizit verhindert. Zumindest solange bis klar ist das es keinen anderen Weg gibt. Man sollte nicht versuchen architektonischen Unsinn durch Reflection ~richtig~ aussehen zu lassen 
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Mo 14.12.09 16:30
Ralf Jansen hat folgendes geschrieben : | Was soll das denn für eine Methode sein die alle Klassen haben aber weder von einem gemeinsamen Vorfahren kommt noch aus einem Interface?
Und wenn dem so ist wer programmiert so was? |
Es gibt Controls von DevExpress, welche die Methode SaveLayoutToStream(Stream stream) implementiert haben.
Ich möchte Control-Objekt(-Referenz) an eine Methode übergeben, die dann SaveLayoutToStream aufruft und intern den Stream in der Datenbank abzuspeichern.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 14.12.09 17:07
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 14.12.09 17:38
Zitat: | Wenn man die Klassen selber nicht ändern kann, was er ja in seinem ersten Posting schon schrieb, hat man halt keine andere Wahl |
Man hat immer die Wahl einen nicht generische Ansatz zu wählen. Darum hätte ich erst auf mehr Details gewartet um zu entscheiden ob eine generische Lösung überhaupt Sinn macht.
Zitat: | Es gibt Controls von DevExpress, welche die Methode SaveLayoutToStream(Stream stream) implementiert haben. |
Wenn du mal eine funktionierende Lösung hast würde mich die interessieren. Es geht ja nur(verglichen mit der gesamt Menge von DevEx Controls) so um 6-7 Klassen die SaveLayoutToStream unterstützen und nicht alle (z.B. die RibbonQuickAccessToolbar) sind Controls.
Edit: bei der NavBar heißt die äquivalente Funktion nicht SaveLayoutToStream sondern nur SaveToStream.
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Di 15.12.09 15:15
Die NavBar kann der Endbenutzer nicht beeinflussen (AFAIK) somit muss ich da auch nichts wegsichern. Ich möchte das nur mit den Controls machen wo der Endbenutzer etwas in der Darstellung anpassen kann. Diese soll er sich auch speichern können (bei mir in der DB)
Paul
ps: Wenns nicht anders geht, werde ichs über die genannte Methode mit Reflection machen.
Stehe leider unter besonderm Zeitdruck, der mir nicht erlaubt viel auszuproobieren. Danke aber für die bisherige Hilfe!
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Do 17.12.09 16:32
Habs jetzt am laufen, sieht etwa so aus:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38:
| private void IterateThrough() {
foreach (System.Windows.Forms.Control einControl in LayoutReference.Controls) { if (einControl != null) {
if (einControl.GetType().ToString().Contains("Grid")) { var t = einControl.GetType(); var m = t.GetProperty("MainView");
var k = m.GetValue(einControl, null); CallMethod(k, "SaveLayoutToStream"); } } } }
private void CallMethod(object o, String fktName) { var t = o.GetType();
Type[] Parameter = new Type[1];
Parameter.SetValue(typeof(System.String), 0);
object[] blub = { LayoutStream }; var m = t.GetMethod(fktName, Parameter); if (m != null) m.Invoke(o, blub);
LayoutStream.Seek(0, System.IO.SeekOrigin.Begin); } |
Musste das so machen, weil eine GridView in GridContro.MainView drin ist.
Der Ansatz ist nicht sehr generisch aber dafür schneller. Ich werde alle SaveTo... Controls separat implementieren wenn ich sie einmal benötigen werde
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Do 17.12.09 19:29
Das ist eine generische Lösung die genau bei einem Control funktioniert. Das hilft nicht wirklich.
Mach es lieber ganz simpel.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| private void IterateThrough() { foreach (System.Windows.Forms.Control einControl in LayoutReference.Controls) { DevExpress.XtraGrid.GridControl grid = einControl as DevExpress.XtraGrid.GridControl; if (grid != null) { grid.MainView.SaveLayoutToStream(LayoutStream); LayoutStream.Seek(0, System.IO.SeekOrigin.Begin); } } } |
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Fr 18.12.09 09:49
Nö, so wird es nicht gehen. Ich habe ja auch buttons, labels und andere Controls im XtraLayout.
Ich kann jetzt nicht alle als Gridcontrol casten. Nur eben die Controls, die ein GridControl sind.
So wie ichs gemacht hab, kann ich mit "Contains("AndereLayoutControls")" andere Controls, welche die SaveLayoutX sachen unterstützen auch aufrufen.
Wenn die GridView direkt in der Control Collection sein würde, könnte ich immer auf die Existenz der SaveLayoutX prüfen und entscprechende ausführen.
Geht aber nicht, da nicht alle sichtbaren Controls direkt im XtraLayout Control Collection drin sind.
|
|
Ralf Jansen
      
Beiträge: 4708
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Fr 18.12.09 11:25
Zitat: | Ich kann jetzt nicht alle als Gridcontrol casten. Nur eben die Controls, die ein GridControl sind. |
Bei cast via as werden alle Controls die nicht dem angefragten Typ entsprechen zu null, darum der Test auf null dahinter. Alle nicht GridControls fallen also frühzeitig raus.
|
|
paul.-b 
      
Beiträge: 26
|
Verfasst: Fr 18.12.09 14:21
Das wusste ich nicht. Dankeschön, ich werds mal so probieren!
|
|