Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Programmierkonstrukt für das Ausführen von beliebigen Methoden mit unterschiedlichen Parametern
Bunnychecker
myCSharp.de - Member



Dabei seit:
Beiträge: 229

Themenstarter:

Programmierkonstrukt für das Ausführen von beliebigen Methoden mit unterschiedlichen Parametern

beantworten | zitieren | melden

Hallo,

ich bin mir nicht sicher wie man folgendes Problem löst.

Ich habe eine Klasse in der es verschiedenste Methoden mit unterschiedlichen Parametern gibt. Die Methoden machen alle nur kleinere Berechnungen.

Nun möchte ich aufbauend auf dieser Klasse eine Logikschicht oben aufsetzen, die mir diese Methoden nun zu bestimmten Zeitpunkten (z.B: 12:53 Uhr) aufruft.

Ich bräuchte dann einen universellen Delegaten oder wie soll ich das Problem lösen?

LG
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Bunnychecker am .
private Nachricht | Beiträge des Benutzers
m0rius
myCSharp.de - Member

Avatar #avatar-3125.png


Dabei seit:
Beiträge: 1043

beantworten | zitieren | melden

Hallo Bunnychecker,

du kannst dein Problem mit Hilfe verschiedener Ansätze lösen.
  • Einerseits kannst du die gewünschten Methoden aufrufen, nachdem eine – vom jetzigen Zeitpunkt ausgehende – Zeitspanne abgelaufen ist. Stichwort: Timer.
  • Andererseits kannst du periodisch, also z.B. alle 5 Minuten, überprüfen lassen, ob du dich in deinem angestrebten Zeitfenster befindest. Weiterhin musst du überprüfen, ob die Methoden nicht bereits ausgeführt worden sind; das regelst du am besten über ein "Ausgeführt"-Flag. Sind beide Bedingungen erfüllt, führst du die Methoden aus. Wurden diese erfolgreich ausgeführt, setzt du das "Ausgeführt"-Flag auf true.

m0rius
Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg
private Nachricht | Beiträge des Benutzers
Bunnychecker
myCSharp.de - Member



Dabei seit:
Beiträge: 229

Themenstarter:

beantworten | zitieren | melden

Danke dir für deine Antwort.

Das war sicher aus meinem Beitrag nicht ganz herauszulesen. Mir ging es dabei vorallem darum, wie ich die unterschiedlichen Signaturen der Methoden in einen Container packe, sodass das Programm dann, wenn der Timer abgelaufen ist oder die zyklische Abfrage ausgeführt werden soll, auch alle Parameter für diesen Methodenaufruf vorhanden sind.
private Nachricht | Beiträge des Benutzers
m0rius
myCSharp.de - Member

Avatar #avatar-3125.png


Dabei seit:
Beiträge: 1043

beantworten | zitieren | melden

Hallo Bunnychecker,

das ist jetzt ein wenig generell. Mit so wenigen Informationen kann ich dir natürlich nicht sagen, wie du es am besten anstelltst, dass "auch alle Parameter für diesen Methodenaufruf vorhanden sind". Ob du diese in Dateien zwischenspeicherst oder sonst wo ablegst, musst du selbst anhand deines konkreten Szenarios entscheiden.

m0rius
Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg
private Nachricht | Beiträge des Benutzers
Bunnychecker
myCSharp.de - Member



Dabei seit:
Beiträge: 229

Themenstarter:

beantworten | zitieren | melden


    class Class1
    {
        public void Method1(string s)
        {
        }

        public void Method2(int i)
        {
        }

        public void Method3(double d, string str)
        {
        }

        /// Weitere Methoden mit unterschiedlichen Signaturen
    }


Nun hätte ich gerne solch eine Liste:

Element0: Methode1(string1)
Element1: Methode3(2.5, string2)
Element2: Methode2(12)
...

Und immer wenn der Timer abgelaufen ist, soll er das nächste Element in der Liste (keine Queue, da die veränderlich bleiben soll) abarbeiten.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Bunnychecker am .
private Nachricht | Beiträge des Benutzers
BhaaL
myCSharp.de - Member

Avatar #erP6yAFiewXrJTqrvg6R.jpg


Dabei seit:
Beiträge: 656

beantworten | zitieren | melden

Zitat von Bunnychecker
Ich bräuchte dann einen universellen Delegaten
Wie wärs mit Action?
In Verbindung mit Lambda Expressions könntest du damit einfach eine Liste befüllen.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

beantworten | zitieren | melden

Hallo Bunnychecker,

ich denke, das geht mit Delegaten (alleine) nicht, sondern man muss die Methode per Reflection aufrufen, denn da kann man die Parameter als Object-Array übergeben. [EDIT]Vorausgesetzt, man will eine abgeschlossene Lösung, die mit beliebigen Parametertypen funktioniert, ohne dass man für jede (weitere) Parameterkombination eigene(n) Adapter(methode) oder zumindest einen entsprechenden Lambda-Ausdruck erstellen muss.[/EDIT] Reflection zu verwenden, verlagert die Typprüfung natürlich zur Laufzeit.

Mit anderen Worten, man merkt sich in der Queue, a) den Delegaten oder gleich die MethodInfo der aufzurufenden Methode, b) das Objekt, für das die Methode aufgerufen werden soll und c) die Parameter der Methode als Object-Array. Dann hat man alles beisammen für den Aufruf per Reflection.

Du solltest auf passende Thread-Titel achten. Wenn es dir nicht auf den Zeitpunkt sondern die Art des Aufrufs ankommt, sollte das schon aus dem Titel hervorgehen ==> geändert

herbivore

PS: Jetzt verstehe ich, glaube ich, wie BhaaL das meint. Man kann natürlich auch Lambda-Ausdrücke in die Queue stellen, wobei der Lambda-Ausdruck selbst keine Parameter bekommt, sondern alle Parameter im Rumpf des Lambda-Ausdrucks direkt an den eigentlichen Methodenaufruf übergeben werden. Deshalb kommt man dann mit dem parameterlosen (nicht generischen) Action-Delegaten aus. Die Parameter kommen dann beim späteren Aufruf - sofern es sich nicht um Literale handelt - aus captured variables, was etwas Vorsicht erfordert, damit auch tatsächlich die gewünschten Werte übergeben werden, siehe Von einem Thread auf einen anderen zugreifen [und captured variables].
private Nachricht | Beiträge des Benutzers
der-schlingel
myCSharp.de - Member

Avatar #avatar-3239.jpg


Dabei seit:
Beiträge: 820
Herkunft: Österreich/Wien

beantworten | zitieren | melden

Wenn du die Typsicherheit behalten möchtest, könntest du das auch per Adapter-Pattern lösen.

Dann würdest du für jede Methode die du aufrufen möchtest, eine Adapter-Klasse schreiben die mit den nötigen Parametern der Methode befüllt wird.

Eine jede Adapter-Klasse muss dann noch ein Interface der Form:


public interface IExecutable 
{
    public void Execute();
}

implementieren. Für deine Methode 3 würde dann ein Adapter z.B. so aussehen:


public class Method3Adapter : IExecutable
{
    public double D { get; set; }
  
    public String Str { get; set; }

    public void Execute() {
       // woher du dann die konkrete Instanz deines Objektes nimmst musst
       // du dir überlegen, hängt davon ab ob es mehrere Instanzen sein sollen,
       // verschiedene Typen sein, etc.
       deineInstanz.Method3(D, Str);
    }
}

Und solche Objekte speicherst du in einer Liste die du dann periodisch aufrufst.

PS: Die Lambda-Lösung würde ich vermeiden. Sie sieht bestimmt im Code sehr elegant aus, ist aber gleichzeitig mit viel Vorsichtz genießen wie herbivore schon ausgeführt hat.
Das oben angeführte Pattern ist zwar nicht so sexy wie Closures aber viel einfacher in Punkto Seiteneffekte sowie Scope zu durchschauen.
As a man thinketh in his heart, so he is.
- Jun Fan
Es gibt nichts Gutes, außer man tut es.
- Erich Kästner
Krawutzi-Kaputzi
- Kasperl
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1498
Herkunft: Düsseldorf

beantworten | zitieren | melden

Aufbauend auf den Ideen von der-schlingel und herbivore:


Beidem Adapter, kann man die nicht auch viel einfacher so gestalten, dass sie drei Eigenschaften vom Typ MethodInfo (Die Methoden-Infos), object (Die Referenz, fals eine vorhanden ist) und object[] (für alle Parameter, wenn es keine gibt, ist das Array einfach leer)

Der Klasse werden die Informationen dann übergeben, oder man baut einen Konstruktor, der als Parameter neben den beiden anderen Eigenschaften direkt die betroffene Methode übernimmt. Dafür kann man dann ja passende Delegaten schreiben und den Konstruktor entsprechend überladen.
Die Überprüfung der Parameter müsste sich ja mit den Informationen von MethodInfo relativ einfach realisieren lassen.

Ich hab das noch nicht ausprobiert, aber so weit ich mich an den Inhalt von MethodInfo erinnern kann, gab es da eine Methode, die neben der Referenz ein Array vom Typ object annimmt und dann die, durch die Referenz von MethodInfo dargestellte, Methode ausführt.

Wenn ich falsch liege lasse ich mich gerne belehren, aber die Idee mit dem Adapter gefällt mir, ich glaube ich schreibe mir gleich mal Einen, der sowas tut^^ Wenn er funktioniert, kann ich ihn ja hier zeigen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
der-schlingel
myCSharp.de - Member

Avatar #avatar-3239.jpg


Dabei seit:
Beiträge: 820
Herkunft: Österreich/Wien

beantworten | zitieren | melden

Das ist dann eine Kombination von Herbivores und meiner Idee.

Sollte aber so machbar sein.
As a man thinketh in his heart, so he is.
- Jun Fan
Es gibt nichts Gutes, außer man tut es.
- Erich Kästner
Krawutzi-Kaputzi
- Kasperl
private Nachricht | Beiträge des Benutzers