0

如何最好地允许输入 ac# 程序来控制方法调用?例如:

假设我们有一个委托类型:

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,但这会更加复杂。

4

3 回答 3

2

这实际上取决于您要涵盖的范围。对于简单的情况,您可以使用开关(我建议并枚举以使其清楚):

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

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

IExecutableCommand但是如果你正在编写一个 shell,那么你需要一些更健壮的东西,比如由各种类实现的某种接口。

interface IExecutableCommand
{
    void Execute(string arg);
}

您将必须实现一些解析器来处理多个调用请求和/或处理更复杂的参数。

如果您想使用反射,请务必验证您的输入!这可以通过仅执行具有自定义属性的方法来完成。

class ExecutableMethodAttribute : Attribute { }

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

用这个属性过滤掉方法很容易:

someAssembly.GetTypes()
  .SelectMany(t => t.GetMethods())
  .Where(mi => mi.GetCustomAttributes(typeof(ExecutableMethodAttribute), true).Any())
于 2011-08-03T07:25:07.780 回答
0
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();
} 
于 2011-08-03T07:24:18.430 回答
0

如果您为 Actions 创建一个值字典,您可以这样做

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

然后你可以循环和处理

foreach (var item in input) _actions[item]();
于 2011-08-03T07:29:36.120 回答