简体   繁体   中英

invoke a method from a string as an inherited class

The problem I'm facing is that I have a user input some basic descriptions of an object and then they specify the type of calculation. Think of it as having the ability to multiply, add, subtract. Same numbers go in, same numbers go out. These are IEnumerable objects of a type. So they enter the numbers in an excel, a class grabs those numbers and i am able to use them like inputedobject.firstnumber, inputedobject.secondnumber etc. The last one is inpytedobject.calculationType. I was thinking since calculationType is already defined if I could take that and call that calculation from that string. So I'd have something like:

var s = invokeMethod (inputedobject.calculationType, inputedobject)

and it would yield the results of calculationType (inputedobject) and I'd do stuff with it. Happy to hear other implementations that would be better. But on this approach I've mentioned I've tried the following to no avail because it was implemented on strings and I don't know how to get it to inherit those objects.

class InvokeString
    {
        public static IEnumerable<eTotal> InvokeStringMethod(string typeName, string methodName, LoanInput loanInput)
        {
            // Get the Type for the class
            Type calledType = Type.GetType(typeName);

            // Invoke the method itself. The string returned by the method winds up in s.
            // Note that stringParam is passed via the last parameter of InvokeMember,
            // as an array of Objects.
            IEnumerable<eTotal> s =  (string)calledType.InvokeMember(
                            methodName,
                            BindingFlags.InvokeMethod | BindingFlags.Public |
                                BindingFlags.Static,
                            null,
                            null,
                            new Object[] { loanInput } );

            // Return the string that was returned by the called method.
            return s;
        }

Seems to me you just need to map those strings to functions, which is easy to do with dictionary full of Func objects.

Start by listing all of your operations in a dictionary, with the key as a string and the value set to a delegate that does the computation. For example:

private Dictionary<string, Func<float,float,float>> _map = 
    new Dictionary<string, Func<float,float,float>>
{
    { "add",      (a,b) => a+b },
    { "subtract", (a,b) => a-b },
    { "multiply", (a,b) => a*b },
    { "divide",   (a,b) => a/b },
};

You can get the right operation with the string provided by the caller, then use the operation just like a regular function. Example:

public float Compute(float[] numbers, string opCode)
{
    var operation = _map[opCode];

    float accumulator = numbers[0];
    foreach (var n in numbers.Skip(1))
    {
        accumulator = operation(accumulator, n);    
    }
    return accumulator;
}

Here is a little test program to show you how to put it all together:

public class Calculator
{
    private Dictionary<string, Func<float,float,float>> _map = new Dictionary<string, Func<float,float,float>>
    {
        { "add", (a,b) => a+b },
        { "subtract", (a,b) => a-b },
        { "multiply", (a,b) => a*b },
        { "divide", (a,b) => a/b },
    };

    public float Compute(float[] numbers, string opCode)
    {
        var operation = _map[opCode];

        float accumulator = numbers[0];
        foreach (var n in numbers.Skip(1))
        {
            accumulator = operation(accumulator, n);    
        }
        return accumulator;
    }
}

public class Program
{
    public static void Main()
    {
        var c = new Calculator();
        Console.WriteLine(c.Compute( new float[] { 2,2 }, "add"));
        Console.WriteLine(c.Compute( new float[] { 3,3 }, "multiply"));
        Console.WriteLine(c.Compute( new float[] {-2,2 }, "subtract"));
        Console.WriteLine(c.Compute( new float[] { 9,3 }, "divide"));
    }
}

Output:

4
9
-4
3

Click here to see the full code in action on DotNetFiddle .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM