c # указать вызов метода на основе ввода? - PullRequest
0 голосов
/ 03 августа 2011

Как лучше всего разрешить вводу программы на c # управлять вызовом метода? Например:

Предположим, у нас есть тип делегата:

delegate void WriteMe(); 

И пара методов:

void PrintInt() { Console.WriteLine(10); }
void PrintString() { Console.WriteLine("Hello world."); }

И позволяет входу выбирать порядок вызова:

public static WriteMe ProcessInvocationInput(int[] val) {
    WriteMe d = null; 
    foreach (int i in val) {
        switch (i) {
            case 1: d += PrintInt; break; 
            case 2: d += PrintString; break; 
        } 
    }
}

И код, который все это называет:

static void Main(string args[]) {
    int[] values = {1, 2, 3}; // Obviously this array could be filled 
                              // from actual input (args, file, wherever)
    WriteMe d = ProcessInvocationInput(values); 

    d(); 
}

Причина, по которой я публикую этот вопрос, заключается в том, что он кажется довольно сложным для реализации того, что кажется простой идеей. Я знаю еще один способ добиться такого поведения с помощью API отражения, но это было бы еще более запутанным.

Ответы [ 3 ]

2 голосов
/ 03 августа 2011

Это действительно зависит от сферы охвата, которую вы пытаетесь охватить. Для простых случаев вы можете использовать переключатель (я бы предложил и enum, чтобы прояснить это):

enum InputCommands
{
    PrintHelloWorld = 1,
    ExecuteFixedBinary = 2,
    ...
}

switch((InputCommands)inputInt)
{
    case InputCommands.PrintHelloWorld: ...
    case InputCommands.ExecuteFixedBinary: ...
}

Но если вы пишете оболочку, вам нужно что-то более надежное, например, какой-то IExecutableCommand интерфейс, реализованный различными классами.

interface IExecutableCommand
{
    void Execute(string arg);
}

Вам потребуется реализовать некоторый синтаксический анализатор для обработки нескольких запросов вызова и / или для обработки более сложных аргументов.

Если вы хотите использовать Reflection, не забудьте подтвердить свои данные! Это можно сделать, только выполнив методы с пользовательским атрибутом.

class ExecutableMethodAttribute : Attribute { }

[ExecutableMethod]
void Foo() 
{ 
   ...
}

Отфильтровать методы с помощью этого атрибута достаточно просто:

someAssembly.GetTypes()
  .SelectMany(t => t.GetMethods())
  .Where(mi => mi.GetCustomAttributes(typeof(ExecutableMethodAttribute), true).Any())
0 голосов
/ 03 августа 2011

Если вы создаете словарь значений для действий, вы можете выполнить

 private static Dictionary<int,Action> _actions=new Dictionary<int,Actions> {
     {1, PrintInt},
     {2, PrintString},
 };

Затем вы можете просто зациклить и обработать

foreach (var item in input) _actions[item]();
0 голосов
/ 03 августа 2011
public static ICollection<Action> ProcessInvocationInput(int[] val)
{
    var actions = new List<Action>();
    foreach (int i in val)
    {
        switch (i)
        {
            case 1: actions.Add(PrintInt);
            case 2: actions.Add(PrintString);
        }
    }

    return actions;
}

...
foreach (var action in ProcessInvocationInput(input))
{
    action();
} 
...