4

私はc#とasp.netで最初の一歩を踏み出し、とても楽しんでいます。今、私は質問があります... phpのようにクラス/メソッドを呼び出すためのC#の関数はありますか?
例えば:

$class = array(
    "foo", // class name
    "bar" // method name
);
$params = array(
    "one",
    "two"
);
call_user_func_array($class, $params); //execute Foo->bar("one","two");
4

3 に答える 3

3

いいえ、それを正確に行うための機能は組み込まれていません。リフレクションを使用して同様のことを行うメソッドを構築することもできますが、それは問題を探す解決策のようです。

void Main()
{
    CallUserFuncArray("UserQuery+Foo", "Bar", "One", "Two");
}

// Define other methods and classes here
public class Foo
{
    public static void Bar(string a, string b){}
}

public void CallUserFuncArray(string className, string methodName, params object[] args)
{
    Type.GetType(className).GetMethod(methodName).Invoke(null, args);
}
于 2012-10-22T03:07:17.243 に答える
2

他の人が指摘しているように、これをシミュレートする方法は複数ありますが、C# には「組み込まれた」機能はありません。最も柔軟な方法はリフレクションを使用することですが、事前に呼び出すメソッドのリストがわかっている場合は、はるかに単純な (そして扱いやすい) 方法で行うことができます。

class Foo
{
    public static string FooA(int p1, int p2) 
    { 
        return "FooA:" + p1 + p2; 
    }
    public static string FooB(int p1, int p2) { return "FooB:" + p1 + p2; }
    public static string FooC(int p1, int p2) { return "FooC:" + p1 + p2; }
}    
class Bar
{
    //You can use Func<int, int, object> instead of a delegate type,
    //but this way is a little easier to read.
    public delegate string Del(int p1, int p2);

    public static string DoStuff()
    {        
        var classes = new Dictionary<string, Dictionary<string, Del>>();
        classes.Add("Foo", new Dictionary<string, Del>());
        classes["Foo"].Add("FooA", Foo.FooA);
        classes["Foo"].Add("FooB", Foo.FooB);
        classes["Foo"].Add("FooC", Foo.FooC);

        //...snip...

        return classes["Foo"]["FooA"](5, 7);
    }
}

ちなみに、これは機能します。

この方法でどのメソッドを利用可能にしたいかわからない場合は、何をしようとしているのかを再考することをお勧めします。文字列を使用して実行パスを選択する唯一の理由は、ユーザーからそれらの文字列を取得することを計画している場合です。このようにアプリケーションの内部の詳細を公開することは非常に禁物であるだけでなく、evalタイプの機能に危険なほど近づいてしまいます。C# にevalメソッドがないのには理由があり、それは設計者がメソッドを入れるのを忘れたからではありません。

于 2012-10-22T05:10:33.863 に答える
1

@StriplingWarriorが言ったように、に相当するものは組み込まれてcall_user_func_arrayいませんが、Reflectionを使用してそのようなことを行うことができます。

問題は、Reflectionコードが非常にすぐに複雑になる可能性があり、あまり注意しないと、脆弱でエラーが発生しやすくなる可能性があることです。

たとえば、次の関数は必要なことを実行します。

public static void CallUserFuncArray(string[] func, params string[] args)
{
    var type = Type.GetType(func[0]);
    if (type == null)
    {
        throw new ArgumentException("The specified Class could not be found");
    }

    var method = type.GetMethod(func[1], BindingFlags.Static | BindingFlags.Public);
    if (method== null)
    {
        throw new ArgumentException("The specified Method could not be found");
    }

    method.Invoke(null, args);
}

あなたはそれをこのように呼びます:

var func = new [] { "Foo", "Bar" };
var args = new [] { "one", "two" };

CallUserFuncArray(func, args);

しかし、問題はたくさんあります。

  • このコードBarは、がパブリック静的メソッドである場合にのみ機能します。
  • オブジェクトのインスタンスメソッドを呼び出す必要がある場合は、まったく新しい複雑さの層があります。
  • args配列内のパラメーターがターゲットメソッドに適切でない場合、コードは爆発します。
  • ここでは、文字列パラメータ以外のものを期待するメソッドの呼び出しはサポートされていません。'Invoke'を呼び出す前に、メソッドで期待される引数の型を照会し、型を変換することは可能ですが、さらに厄介になります。
  • これらに対応する必要がある場合は、このコードの複雑さをさらに吹き飛ばすエッジケースがさらにたくさんあります。

(dotNetRocksの名声の)Carl Franklinを言い換えると:

解決する必要のある問題があったので、Reflectionを使用しました。今、私は2つの問題を抱えています。

私はあなた自身がこの種のことをする必要があると思います、そしてあなたはおそらくあなたの全体的なデザインを再考する必要があります。

于 2012-10-22T04:03:34.953 に答える