web-dev-qa-db-fra.com

Est-il possible de stocker des fonctions dans un dictionnaire?

J'ai un message qui arrive dans mon application C # qui est un objet sérialisé en JSON, quand je le désérialise j'ai un "Nom" string et une "Payload" string[], Je veux pouvoir prendre le "Nom" et le rechercher dans un dictionnaire de fonctions, en utilisant le tableau "Payload" comme paramètres, puis prendre la sortie pour retourner au client qui envoie le message, est-ce possible dans C #?

J'ai trouvé une réponse de débordement de pile ici où la deuxième partie semble plausible mais je ne sais pas de quoi je parle avec State

35
Trotski94

On dirait que vous probablement voulez quelque chose comme:

Dictionary<string, Func<string[], int>> functions = ...;

Cela suppose que la fonction renvoie un int (que vous n'avez pas spécifié). Donc, vous l'appeleriez comme ceci:

int result = functions[name](parameters);

Ou pour valider le nom:

Func<string[], int> function;
if (functions.TryGetValue(name, out function))
{
    int result = function(parameters);
    ...
}
else
{
    // No function with that name
}

Il n'est pas clair d'où vous essayez de remplir functions, mais s'il s'agit de méthodes de la même classe, vous pourriez avoir quelque chose comme:

Dictionary<string, Func<string[], int>> functions = 
    new Dictionary<string, Func<string[], int>>
{
    { "Foo", CountParameters },
    { "Bar", SomeOtherMethodName }
};

...

private static int CountParameters(string[] parameters)
{
    return parameters.Length;
}

// etc
49
Jon Skeet

Vous pouvez créer un dictionnaire de string comme clé et un Action<string[]> comme valeur et l'utiliser, par exemple:

var functions = new Dictionary<string, Action<string[]>>();

functions.Add("compute", (p) => { /* use p to compute something*/ });
functions.Add("load", (p) => { /* use p to compute something*/ });
functions.Add("process", (p) => { /* use p to process something*/ });

Vous pouvez l'utiliser après avoir désérialisé votre paramètre de message, vous pouvez utiliser le dictionnaire functions:

public void ProcessObject(MessageDTO message)
{
    if (functions.ContainsKey(message.Name))
    {
        functions[name](message.Parameters);
    }
}
5
Felipe Oriani

Oui.

var functions = new Dictionary<string, Func<string[], string[]>>();
functions.Add("head", x => x.Take(1).ToArray());
functions.Add("tail", x => x.Skip(1).ToArray());
var result = functions["tail"](new [] {"a", "b", "c"});
3
stovroz

Quelque chose de similaire à ceci:

public class Methods
{
    public readonly Dictionary<string, Func<string[], object>> MethodsDict = new Dictionary<string, Func<string[], object>>();

    public Methods()
    {
        MethodsDict.Add("Method1", Method1);
        MethodsDict.Add("Method2", Method2);
    }

    public string Execute(string methodName, string[] strs)
    {
        Func<string[], object> method;

        if (!MethodsDict.TryGetValue(methodName, out method))
        {
            // Not found;
            throw new Exception();
        }

        object result = method(strs);

        // Here you should serialize result with your JSON serializer
        string json = result.ToString();

        return json;
    }

    public object Method1(string[] strs)
    {
        return strs.Length;
    }

    public object Method2(string[] strs)
    {
        return string.Concat(strs);
    }
}

Notez que vous pouvez tout faire static, si les méthodes n'ont pas besoin d'accéder aux données ailleurs.

Le type de retour que j'ai choisi pour les délégués est object. De cette façon, la méthode Execute peut la sérialiser librement vers Json.

2
xanatos

Ma solution avec des paramètres d'entrée et un int comme clé d'invocation:

  private static Dictionary<int, Action> MethodDictionary(string param1, string param2, int param3) => new Dictionary<int, Action>
    {
            {1 , () =>   Method1(param1, param2, param3) },
            {2 , () =>   Method2(param1, param2, param3) },
            {3 , () =>   Method3(param1, param2, param3) },
            {4 , () =>   Method4(param1, param2, param3) },
            {5 , () =>   Method5(param1, param2, param3) }
    };

Et pour invoquer une méthode:

 var methodDictionary = MethodDictionary("param1", "param2", 1);
 methodDictionary[2].Invoke();

Cela exécutera Méthode2.

J'espère que cela aide!

0
user2402666