2010-12-30 13 views
0

私はWebアプリケーション用のルータを作成しようとしています(はい、ソリューションは既に存在します)。方法の参照方法は?

class Route 
{ 
    public static RegexOptions DefaultOptions = RegexOptions.IgnoreCase; 

    Regex regex; 
    Type controller; 
    MethodInfo action; 

    public Route(string pattern, Type controller) 
    { 
     this.regex = new Regex(string.Format("^(?:{0})$", pattern), DefaultOptions); 
     this.controller = controller; 
    } 
} 

そして、この:

は、これまでのところ私はこれを持って

Route[] routes = { 
     new Route(@"/user:(?<id>\d+)", typeof(UserController)) 
    }; 

URLがその正規表現と一致すると、そのクラスcontroller方法actionを呼び出す必要があります。私はtypeof()がクラスを渡すことができる唯一の方法だと思っていますが、方法についてはどうですか?

私はそれを呼び出すことができるはずですが、APIの観点から、Routeコンストラクタの3番目の引数はどのようなものでなければならないと思います。

私はいくつかの文字列の俗語ではなく、強く型付けされた解決法を好んでいます。

+0

アクションメソッドはどのように呼び出す必要がありますか? –

+0

@Martinho:ハァッか。 「行動」はいいです。私の質問は構文についてです。理想的には、 'new Route(" pattern "、UserController.Method)'と書くだけですが、C#はそのような構文をサポートしていません。 – mpen

答えて

1

あなたは存在しないinfoof operatorを探しています。

残念ながら、それは存在しません。

最も簡単な答えは文字列を取ることです。
また、expression treeを受け取ることもできます。
式ツリーを使用することの欠点は、呼び出し元がすべてのパラメータを渡す必要があることです。
フレームワークに(Expression<Func<parameters, ResultType>>を取って)作業し、おそらく式ツリーをコンパイルしてアクションを呼び出すことさえできます。あなたはこのようなものを作成することができます

+1

'infoof'の記事では、私が本当に考えなかったいくつかの問題について言及しています...コンパイル時の型の安全性を得ていないとしても、おそらく文字列を使う方が良いかもしれません。 – mpen

+0

はい;それは素晴らしいブログの投稿です。 – SLaks

+0

しかし、あいまいさに対処するためには、すべての可能なマッチで 'MethodInfo []'を返さなければなりません:) – mpen

1

(反射よりもはるかに高速の通話になります):

MethodInfo GetMethodInfo(LambdaExpression expression) 
{ 
    var call = expression.Body as MethodCallExpression; 
    if(call == null) throw new ArgumentException("Must be a method call","expression"); 
    return call.Method; 
} 

MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression) 
{ 
    return GetMethodInfo(expression); 
} 

MethodInfo GetMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression) 
{ 
    return GetMethodInfo(expression); 
} 

をそして、このようにそれを使用します。

MethodInfo action = GetMethodInfo((UserController c) => c.ActionMethod()); 
// or 
MethodInfo action = GetMethodInfo((UserController c) => 
             c.ActionMethodWithParams(default(int))); 

これはすぐにメソッドを呼び出すことはありませんなぜなら、それは表現木、すなわち、メソッド呼び出しを表す構文木であるからです。

+0

これはコントローラメソッドがパラメータを取らないことを前提としています。それ以外の場合は 'null'と' default() 'を渡す必要があります – statenjason

+0

ああ!いくつかの人々がこれらの "表現木"について言及しましたが、誰もコード例を提供しませんでした。ありがとうございました:) – mpen

+0

@statenjason:いいえ、コントローラーのアクションについて何も想定していません(数分間、戻り値を想定していましたが、パラメーターについては何もしませんでした)。しかし、はい、ダミー値を渡さなければなりません。私は、過負荷の選択に役立つので、デフォルトを優先します。おかげで、ソリューションの悪くないです –

3

私はインスタンスなしでシャープでインスタンスメソッドを参照する方法はないと思います。 APIのユーザーが渡すMethodInfoオブジェクトを定義しない限り、文字列名が最適な方法です。

static class Program 
{ 
    static void Main() 
    { 
     Route r = new Route("pattern", typeof(UserController), "Action"); 
    } 
} 

public class Route 
{ 
    public Route(string pattern, Type type, string methodName) 
    { 
     object objectToUse = Activator.CreateInstance(type, null); 
     MethodInfo method = type.GetMethod(methodName); 
     string[] args = new string[1]; 
     args[0] = "hello world"; 
     method.Invoke(objectToUse, args); 
    } 
} 

public class UserController 
{ 
    public void Action(string message) 
    { 
     MessageBox.Show(message); 
    } 
} 
+0

: 'Action'はUserControllerででインスタンスメソッド...であればD – mpen

+0

待ち...'新しいコールバック(アクション) '、どのようにこれはコンパイルさえありませんか? – mpen

+0

@Ralph:Callback' 'のような[代理人](http://msdn.microsoft.com/en-us/library/ms173171は(VS.80%の29.aspx)とすることができるコードの「個のように、メソッドを表します実行」。METHODINFOは同様の方法を表して 『』名前を持つメンバーと署名。 –

関連する問題