17

以下のコードでは、8080 ポートへの呼び出しを待機しています。

static void Main()
{
  HttpListener listener = new HttpListener();
  listener.Prefixes.Add("http://*:8080/");
  listener.Start();
  while(isRunning)
  {
     HttpListenerContext ctx = listener.GetContext();
     new Thread(new Worker(ctx).ProcessRequest).Start();
  }
}

特定の URL パターンを異なる動作にマッピングすることは可能ですか? REST スタイルのサーバーを実現したい。つまり、localhost:8080/person/1を呼び出すと getPersonH​​andler(int) が起動する

[Mapping("*:8080/person/$id")]
public void getPersonHandler(int id){...}

構文は、私が知っている JAX-RS ライブラリーに対するMapping私自身の希望的アナロジーにすぎません。私はC#で同じことをしたい(aspではなくデスクトップC#)

4

2 に答える 2

20

属性なしで同様の効果を得ることができます

HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
while (true)
{
    HttpListenerContext ctx = listener.GetContext();
    ThreadPool.QueueUserWorkItem((_) =>
    {
        string methodName = ctx.Request.Url.Segments[1].Replace("/", "");
        string[] strParams = ctx.Request.Url
                                .Segments
                                .Skip(2)
                                .Select(s=>s.Replace("/",""))
                                .ToArray();


        var method = this.GetType().GetMethod(methodName);
        object[] @params = method.GetParameters()
                            .Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType))
                            .ToArray();

        object ret = method.Invoke(this, @params);
        string retstr = JsonConvert.SerializeObject(ret);
    });

使用法は次のとおりです。

http://localhost:8080/getPersonHandler/333

本当に属性を使用したい場合

HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
while (true)
{
    HttpListenerContext ctx = listener.GetContext();
    ThreadPool.QueueUserWorkItem((_) =>
    {
        string methodName = ctx.Request.Url.Segments[1].Replace("/", "");
        string[] strParams = ctx.Request.Url
                                .Segments
                                .Skip(2)
                                .Select(s=>s.Replace("/",""))
                                .ToArray();

        var method = this.GetType()
                            .GetMethods()
                            .Where(mi => mi.GetCustomAttributes(true).Any(attr => attr is Mapping && ((Mapping)attr).Map == methodName))
                            .First();

        object[] @params = method.GetParameters()
                            .Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType))
                            .ToArray();

        object ret = method.Invoke(this, @params);
        string retstr = JsonConvert.SerializeObject(ret);
    });
}

次に、 as を使用できhttp://localhost:8080/Person/333、定義は次のようになります

class Mapping : Attribute
{
    public string Map;
    public Mapping(string s)
    {
        Map = s;
    }
}

[Mapping("Person")]
public void getPersonHandler(int id)
{
    Console.WriteLine("<<<<" + id);
}
于 2012-04-04T19:29:55.663 に答える
8

.NET 4.0 以降で作業していて、プラグインできる既存の REST サーバー ソリューションを探している場合 (そのように聞こえます)、Grapevineを調べてみてください。これは NuGet を使用して入手でき、プロジェクト wikiにはサンプル コードがたくさんあります。さらに、これはオープン ソースであるため、それがどのように達成されるかを確認したいだけであれば、そこにすべてのソース コードが表示されます。

パス情報 (正規表現を使用) とリクエスト メソッド (GET、POST など) でリクエストをフィルタリングできます。

私はプロジェクトの作成者であり、あなたが説明したものと同様のニーズがありました. ここや他の場所で見つけたリソースを使用して、Grapevine を構築し、再び必要になったときにいつでも解決策をポケットに入れることができるようにしました ( DRY )。

于 2014-10-29T17:35:20.830 に答える