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

  • »
  • Community
  • |
  • Diskussionsforum
Delegaten mit Verweis aus Variabler erstellen
chrisrabe
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

Delegaten mit Verweis aus Variabler erstellen

beantworten | zitieren | melden

Hallo Forum,

auf meiner nun wirklich langen und erfolglosen Suche nach einer Lösung bin ich hier im Forum gelandet und hoffe auf Eure Hilfe.

In VisualStudio 2008 und 2010 versuche ich in C# einen Kommando Parser zu erstellen, der eingehende RS232 Antworten eines externen Gerätes interpretiert und eine entsprechende Funktion aufruft.
Die zu erkennenden Kommandos wie die dazu gehörig auszuführenden Funktionen möchte ich in einem 2-dimensionalen Stringarray verwalten etwa so:

SNR, SaveSN
Typ, ShowTyp
...


Nach Erkennung eines Kommandos soll irgendwie (ich dachte mit Delegaten) die entsprechende Funktion/Methode aufgerufen werden, also irgendwie so:


string[,] MyArray = new string[2, 2] { { "SNR", "SaveSN" }, { "Typ", "ShowTyp" } };
string TargetFunction = MyArray[0][0];
fncPtr = TargetFunction;
SNR z.B. ist also eine Kennung die per RS232 kommt, SaveSN der Name einer Funktion die bei Erkennung auszuführen ist.

Mit den Delegaten habe ich zwar geschafft eine Funktion aufzurufen, aber die Zuweisung des auszuführenden Methoden Namens müsste über eine Variable erfolgen die also je nach Kommando andere Namen enthält. Bei obiger Zeile will er aber die Funktion mit dem Namen "TargetFunction" ausführen die es natürlich nicht gibt.

Was kann man den machen, um diese Zuweisung per Variable zu ermöglichen?

Viele Grüße
Christian
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15807
Herkunft: BW

beantworten | zitieren | melden

Musst via Reflection die Methode aus der Klasse suchen; die anschließende MethodInfo kannste per Invoke aufrufen.
private Nachricht | Beiträge des Benutzers
Sarc
myCSharp.de - Member



Dabei seit:
Beiträge: 426

beantworten | zitieren | melden

Schlauer wäre es die Methoden gleich als Delegates abzulegen, dann hast du auch keine Magic-Strings.
Z.b. so in etwa (abhängig davon wie deine Methodensignaturen aussehen):


var actions = new Dictionary<string, Action>();
actions.Add("SNR", SaveSN);
...

var a =actions["SNR"]; // Action holen
a(); // Aufruf der Methode

...

private void SaveSN()
{
  ...
}
Alternativ kannst du auch den generische Action-Delegate verwenden, oder Func<> wenn deine Methoden Rückgabewerte haben.
private Nachricht | Beiträge des Benutzers
chrisrabe
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Guten Morgen, Abt und Sarc,

vielen Dank für Eure Tipps. Denke das hilft mir weiter.
private Nachricht | Beiträge des Benutzers
witte
myCSharp.de - Member



Dabei seit:
Beiträge: 966

beantworten | zitieren | melden

Schau Dir mal das Strategie pattern an.
private Nachricht | Beiträge des Benutzers
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

beantworten | zitieren | melden

Wie wäre es denn die ganze sache in eine Klasse zu verpacken:
z.B


static void Main()
{
ComandoParser.Execute("SNR");
            ComandoParser.ShowTyp = () => {
                //do something
            };
            ComandoParser.Execute("Typ");
}

    public static class ComandoParser
    {
        public static KeyValueList<string, string> MyFunctions;

        static ComandoParser()
        {
            MyFunctions = new KeyValueList<string, string>();
            MyFunctions.Add("SNR", "SaveSN", SaveSN);
            MyFunctions.Add("Typ", "ShowTyp", ShowTyp);
        }

        public static void Execute(string Key)
        {
            foreach (var item in MyFunctions[Key])
            {
                item.Execute();
            }
        }

        public static void SaveSN()
        {
            //do something
        }

        public static del ShowTyp;
    }

    public class KeyValueList<TKey, TValue> : List<tuple<TKey, TValue>>
    {
        public void Add(TKey key, TValue value, del d)
        {
            base.Add(new tuple<TKey, TValue>(key, value, d));
        }

        public IEnumerable<tuple<TKey, TValue>> this[TKey key]
        {
            get
            {
                return this.Where(item => item.key.Equals(key));
            }
        }

    }

    public delegate void del();

    public class tuple<TKey, TValue>
    {
        public TKey key { get; set; }
        public TValue value { get; set; }

        public del d;

        public tuple(TKey _key, TValue _value, del _d)
        {
            key = _key;
            value = _value;
            d = _d;
        }

        public void Execute()
        {
            if (d != null)
                d.DynamicInvoke();
        }
    }

private Nachricht | Beiträge des Benutzers
chrisrabe
myCSharp.de - Member



Dabei seit:
Beiträge: 22

Themenstarter:

beantworten | zitieren | melden

Hallo Robin,

das klingt im Grunde auch gut, sofern der eigentliche Aufruf

ComandoParser.Execute("SNR");
eben eine Variable verträgt anstelle des "SNR", also

ComandoParser.Execute(Funktion);
.
Ich muss es ausprobieren... Danke für diesen Ansatz


Hallo Witte,

das kannte ich nicht. Interessante Idee, die ich nochmals lesen werde.
Danke
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 chrisrabe,

dass der Name einer Methode als Literal (und ohne folgende öffnende runde Klammer) vom Compiler als Delegat auf die Methode interpretiert wird, sollte man schon wissen, zumindest, wenn man das Kapitel über Delegaten in einem guten C#-Buch gelesen hat.

Bitte beachte insofern [Hinweis] Wie poste ich richtig? Punkt 1.1.1 und 1.1.

Wenn durch den Methodennamen (und ggf. durch das Objekt, auf das sich die Methode bezieht) die Methode nicht eindeutig identifiziert werden kann, ist die folgende Syntax erforderlich, um die Mehrdeutigkeit zu beseitigen:

new GewuenschterDelegatTyp (MethodenName)

Auch das fällt noch unter Grundlagen.

Natürlich könnte man per Reflection aus einem Magic-String, der den Methodennamen enthält, auch einen Delegaten erhalten, aber das ist hier überhaupt nicht nötig.

Ansonsten sollten in diesem Thread bereits alle relevanten Ansätze und Strichworte zum Thema genannt worden sein.

herbivore
private Nachricht | Beiträge des Benutzers