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ただし、シェルを作成している場合は、さまざまなクラスによって実装されたある種のインターフェイスなど、より堅牢なものが必要です。

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())
于 2011-08-03T07:25:07.780 に答える
0

アクションの値のディクショナリを作成すると、次のことができます

 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 に答える
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 に答える