webentwicklung-frage-antwort-db.com.de

C # Funktionen in einem Wörterbuch speichern

Wie erstelle ich ein Wörterbuch, in dem ich Funktionen speichern kann?

Vielen Dank.

Ich habe etwa 30+ Funktionen, die vom Benutzer ausgeführt werden können. Ich möchte die Funktion auf diese Weise ausführen können:

   private void functionName(arg1, arg2, arg3)
   {
       // code
   }

   dictionaryName.add("doSomething", functionName);

    private void interceptCommand(string command)
    {
        foreach ( var cmd in dictionaryName )
        {
            if ( cmd.Key.Equals(command) )
            {
                cmd.Value.Invoke();
            }
        }
    }

Die Funktionssignatur ist jedoch nicht immer gleich und hat daher unterschiedliche Argumente. 

79
chi

So was:

Dictionary<int, Func<string, bool>>

Dadurch können Sie Funktionen speichern, die einen String-Parameter annehmen und boolean zurückgeben.

dico[5] = foo => foo == "Bar";

Oder wenn die Funktion nicht anonym ist:

dico[5] = Foo;

wo Foo wie folgt definiert ist:

public bool Foo(string bar)
{
    ...
}

AKTUALISIEREN: 

Nachdem Sie Ihr Update gesehen haben, scheinen Sie die Signatur der Funktion, die Sie aufrufen möchten, nicht im Voraus zu kennen. Um eine Funktion aufzurufen, müssen Sie in .NET alle Argumente übergeben. Wenn Sie nicht wissen, was die Argumente sind, können Sie dies nur durch Reflektion erreichen.

Und hier ist eine andere Alternative:

class Program
{
    static void Main()
    {
        // store
        var dico = new Dictionary<int, Delegate>();
        dico[1] = new Func<int, int, int>(Func1);
        dico[2] = new Func<int, int, int, int>(Func2);

        // and later invoke
        var res = dico[1].DynamicInvoke(1, 2);
        Console.WriteLine(res);
        var res2 = dico[2].DynamicInvoke(1, 2, 3);
        Console.WriteLine(res2);
    }

    public static int Func1(int arg1, int arg2)
    {
        return arg1 + arg2;
    }

    public static int Func2(int arg1, int arg2, int arg3)
    {
        return arg1 + arg2 + arg3;
    }
}

Bei diesem Ansatz müssen Sie noch die Anzahl und den Typ der Parameter kennen, die an die jeweilige Funktion am entsprechenden Index des Wörterbuchs übergeben werden müssen. Andernfalls erhalten Sie einen Laufzeitfehler. Wenn Ihre Funktionen keine Rückgabewerte enthalten, verwenden Sie System.Action<> anstelle von System.Func<>.

97
Darin Dimitrov

Die Funktionssignatur ist jedoch nicht immer das gleiche, also unterschiedlich Anzahl der Argumente.

Beginnen wir mit einigen Funktionen, die folgendermaßen definiert sind:

private object Function1() { return null; }
private object Function2(object arg1) { return null; }
private object Function3(object arg1, object arg3) { return null; }

Sie haben wirklich zwei mögliche Optionen zur Verfügung:

1) Halten Sie die Typsicherheit aufrecht, indem Sie die Funktion Ihrer Kunden direkt aufrufen.

Dies ist wahrscheinlich die beste Lösung, es sei denn, Sie haben sehr gute Gründe, um von diesem Modell zu brechen.

Wenn Sie davon sprechen, Funktionsaufrufe abzufangen, klingt es für mich, als würden Sie versuchen, virtuelle Funktionen neu zu erfinden. Es gibt viele Möglichkeiten, um diese Art von Funktionalität aus der Box zu bekommen, z. B. von einer Basisklasse zu erben und ihre Funktionen zu überschreiben.

Es klingt für mich wie Sie wollen eine Klasse, die eher eine wrapper ist als eine abgeleitete Instanz einer Basisklasse.

public interface IMyObject
{
    object Function1();
    object Function2(object arg1);
    object Function3(object arg1, object arg2);
}

class MyObject : IMyObject
{
    public object Function1() { return null; }
    public object Function2(object arg1) { return null; }
    public object Function3(object arg1, object arg2) { return null; }
}

class MyObjectInterceptor : IMyObject
{
    readonly IMyObject MyObject;

    public MyObjectInterceptor()
        : this(new MyObject())
    {
    }

    public MyObjectInterceptor(IMyObject myObject)
    {
        MyObject = myObject;
    }

    public object Function1()
    {
        Console.WriteLine("Intercepted Function1");
        return MyObject.Function1();
    }
    public object Function2(object arg1)
    {
        Console.WriteLine("Intercepted Function2");
        return MyObject.Function2(arg1);
    }

    public object Function3(object arg1, object arg2)
    {
        Console.WriteLine("Intercepted Function3");
        return MyObject.Function3(arg1, arg2);
    }
}

2) OR ordnet die Eingabe Ihrer Funktionen einer gemeinsamen Schnittstelle zu.

Dies kann funktionieren, wenn alle Funktionen miteinander zusammenhängen. Zum Beispiel, wenn Sie ein Spiel schreiben und alle Funktionen einen Teil des Inventars des Spielers oder des Spielers betreffen. Sie würden mit so etwas enden:

class Interceptor
{
    private object function1() { return null; }
    private object function2(object arg1) { return null; }
    private object function3(object arg1, object arg3) { return null; }

    Dictionary<string, Func<State, object>> functions;

    public Interceptor()
    {
        functions = new Dictionary<string, Func<State, object>>();
        functions.Add("function1", state => function1());
        functions.Add("function2", state => function2(state.arg1, state.arg2));
        functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3));
    }

    public object Invoke(string key, object state)
    {
        Func<object, object> func = functions[key];
        return func(state);
    }
}
9
Juliet

Warum verwenden Sie nicht params object[] list für Methodenparameter und führen Sie einige Überprüfungen in Ihren Methoden (oder in der Aufruflogik) durch. Dies ermöglicht eine variable Anzahl von Parametern.

1
wvd_vegt

Im folgenden Szenario können Sie ein Wörterbuch mit Elementen verwenden, um als Eingabeparameter zu senden und die Ausgabeparameter zu erhalten.

Fügen Sie zuerst die folgende Zeile hinzu:

using TFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Collections.Generic.IDictionary<string, object>>;

Definieren Sie dann in Ihrer Klasse das Wörterbuch wie folgt:

     private Dictionary<String, TFunc> actions = new Dictionary<String, TFunc>(){

                        {"getmultipledata", (input) => 
                            {
                                //DO WORKING HERE
                                return null;
                            } 
                         }, 
                         {"runproc", (input) => 
                            {
                                //DO WORKING HERE
                                return null;
                            } 
                         }
 };

Auf diese Weise können Sie diese anonymen Funktionen mit einer ähnlichen Syntax ausführen:

var output = actions["runproc"](inputparam);
0
Farax

Hey, ich hoffe das hilft. Aus welcher Sprache kommst du?

internal class ForExample
{
    void DoItLikeThis()
    {
        var provider = new StringMethodProvider();
        provider.Register("doSomethingAndGetGuid", args => DoSomeActionWithStringToGetGuid((string)args[0]));
        provider.Register("thenUseItForSomething", args => DoSomeActionWithAGuid((Guid)args[0],(bool)args[1]));


        Guid guid = provider.Intercept<Guid>("doSomethingAndGetGuid", "I don't matter except if I am null");
        bool isEmpty = guid == default(Guid);
        provider.Intercept("thenUseItForSomething", guid, isEmpty);
    }

    private void DoSomeActionWithAGuid(Guid id, bool isEmpty)
    {
        // code
    }

    private Guid DoSomeActionWithStringToGetGuid(string arg1)
    {
        if(arg1 == null)
        {
            return default(Guid);
        }
        return Guid.NewGuid();
    }

}
public class StringMethodProvider
{
    private readonly Dictionary<string, Func<object[], object>> _dictionary = new Dictionary<string, Func<object[], object>>();
    public void Register<T>(string command, Func<object[],T> function)
    {
        _dictionary.Add(command, args => function(args));
    }
    public void Register(string command, Action<object[]> function)
    {
        _dictionary.Add(command, args =>
                                     {
                                         function.Invoke(args);
                                         return null;
                                     } );
    }
    public T Intercept<T>(string command, params object[] args)
    {
        return (T)_dictionary[command].Invoke(args);
    }
    public void Intercept(string command, params object[] args)
    {
        _dictionary[command].Invoke(args);
    }
}
0
smartcaveman

Definieren Sie das Wörterbuch und fügen Sie die Funktionsreferenz als Wert hinzu. Verwenden Sie System.Action als Typ:

using System.Collections;
using System.Collections.Generic;

public class Actions {

    public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>();

    public Actions() {
        myActions ["myKey"] = TheFunction;
    }

    public void TheFunction() {
        // your logic here
    }
}

Dann rufe es mit auf:

Actions.myActions["myKey"]();
0
modle13