James T
James T

Reputation: 1156

Is it possible to store functions in a dictionary?

I have a message coming into my C# app which is an object serialized as JSON, when i de-serialize it I have a "Name" string and a "Payload" string[], I want to be able to take the "Name" and look it up in a function dictionary, using the "Payload" array as its parameters and then take the output to return to the client sending the message, is this possible in C#?

I've found a stack overflow answer here where the second part seems plausible but i don't know what I'm referencing with State

Upvotes: 35

Views: 19056

Answers (5)

Miguelillo
Miguelillo

Reputation: 21

My solution with input parameters, and a int as Key of Invoke:

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

And to invoke a method:

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

This will execute Method2.

Hope it helps!

Upvotes: 0

Felipe Oriani
Felipe Oriani

Reputation: 38618

You can create a dictionary of string as a key and a Action<string[]> as a value and use it, for sample:

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*/ });

You could use it after you deserialize your message parameter, you could use the functions dictionary:

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

Upvotes: 5

stovroz
stovroz

Reputation: 7075

Yes.

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

Upvotes: 3

xanatos
xanatos

Reputation: 111910

Something similar to this:

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

Note that you could make it all static, if the methods don't need to access data from somewhere else.

The return type I chose for the delegates is object. In this way the Execute method can serialize it to Json freely.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502396

It sounds like you probably want something like:

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

This is assuming the function returns an int (you haven't specified). So you'd call it like this:

int result = functions[name](parameters);

Or to validate the name:

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

It's not clear where you're trying to populate functions from, but if it's methods in the same class, you could have something like:

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

Upvotes: 54

Related Questions