Laden...

Delegaten mit Verweis aus Variabler erstellen

Erstellt von chrisrabe vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.088 Views
Thema geschlossen
C
chrisrabe Themenstarter:in
25 Beiträge seit 2014
vor 10 Jahren
Delegaten mit Verweis aus Variabler erstellen

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

16.806 Beiträge seit 2008
vor 10 Jahren

Musst via Reflection die Methode aus der Klasse suchen; die anschließende MethodInfo kannste per Invoke aufrufen.

S
417 Beiträge seit 2008
vor 10 Jahren

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.

C
chrisrabe Themenstarter:in
25 Beiträge seit 2014
vor 10 Jahren

Guten Morgen, Abt und Sarc,

vielen Dank für Eure Tipps. Denke das hilft mir weiter.

W
955 Beiträge seit 2010
vor 10 Jahren

Schau Dir mal das Strategie pattern an.

R
212 Beiträge seit 2012
vor 10 Jahren

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();
        }
    }


C
chrisrabe Themenstarter:in
25 Beiträge seit 2014
vor 10 Jahren

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

49.485 Beiträge seit 2005
vor 10 Jahren

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

Thema geschlossen