2

ASP.Net 用の代替 MVC フレームワークを設計しています。フレームワークに対する私の目標の 1 つは、「魔法」をできるだけ少なくすることです。私が持っている唯一のリフレクションは、フォーム、クエリ文字列などを単純な古いクラスにバインドすることです(無視、変換などのオプションの属性を使用)。そのため、クラス/メソッドの検出は一切行いません。すべてが非常に明確でなければなりません。API「シェイプ」を約 3 回繰り返しました。最初の 2 つは魔法を持たないという私の目標を達成しましたが、非常に冗長で読みにくいものでした..通常、コントローラーは MVC フレームワークが行うべき重い仕事をしなければなりませんでした。

そのため、この 3 回目の反復では、正しく行うために非常に懸命に努力してます。私が別のやり方で少し物議をかもしていることの 1 つは、ルーティング コードです。すべてが明示的であり、リフレクションは推奨されないため、ルートを解決するためにコントローラー内の属性を検索することはできません。すべてをルート レベルで指定する必要があります。最初の反復ではこれは行われませんでしたが、非常に扱いにくく冗長なコントローラーになりました...

現在、ルートを指定するための流暢な API があります。これは、私が最初に想像したものを少し超えており、現在では、コントローラーのメソッドで何ができるか、何を受け入れる必要があるかを指定する一種の方法として機能しています。

実際のコードに進みます。実装は無関係です。本当に知っておく必要がある唯一のことは、多くのジェネリック型が含まれているということです。そのため、いくつかのルーティングの簡単なサンプルを次に示します。

var router=new Router(...);
var blog=router.Controller(() => new BlogController());
blog.Handles("/blog/index").With((ctrl) => ctrl.Index());
blog.Handles("/blog/{id}").With((ctrl,model) => ctrl.View(model["id"])).WhereRouteLike((r) => r["id"].IsInteger()); //model defaults to creating a dictionary from route parameters
blog.Handles("/blog/new").UsingFormModel(() => new BlogPost()).With((ctrl, model) => ctrl.NewPost(model)); //here model would be of type BlogPost. Also, could substitue UsingRouteModel, UsingQueryStringModel, etc

WhereModelIsLikeモデルの検証を行うなど、実装できる他の方法もいくつかあります。しかし、この種の「仕様」はルーティング層に属しますか? ルーティング層で指定する必要がある制限は何ですか? 検証するためにコントローラに何を残す必要がありますか?

ルーティング層に心配をかけすぎていませんか?

4

2 に答える 2

2

ルーティングが冗長すぎると思います。20 個のコントローラーに対してそのようなコードを書きたくありません。特に、それは本当に繰り返されるからです。
ここで見られる問題は、デフォルトのケースでも冗長な宣言が必要であるということです。これらの冗長な宣言は、特別な場合にのみ必要です。
表現力豊かで読みやすいですが、高度な機能をパッケージ化することを検討することをお勧めします。

次の仕様を見てください。そして、それは単一のコントローラーでの単一のアクションのためだけです:

blog.Handles("/blog/new")
    .UsingFormModel(() => new BlogPost())
    .With((ctrl, model) => ctrl.NewPost(model))
    .WhereModelIsLike(m => m.Status == PostStatus.New);

コードの量をわずかに減らす 1 つの方法は、ルート フォルダーの指定を許可することです。

var blog=router.Controller(() => new BlogController(), "/blog");
blog.Handles("index").Wi..
blog.Handles("{id}").Wit..
blog.Handles("new").Usin..

デフォルトのケースのコードを削減するもう 1 つのアイデアは、デフォルト アクションごとに 1 つのインターフェイスを導入することです。コントローラーは、サポートされているアクションのインターフェースを実装する必要があります。

このようなものかもしれません:

public interface ISupportIndex
{
    void Index();
}

public interface ISupportSingleItem
{
    void View(int id);
}

blog.HandlesIndex();これで、 、 などのメソッドを提供できますblog.HandlesSingleItem();
これらのメソッドは既存のメソッドと同じものを返すため、結果をさらに絞り込むことができます。
それらは、コントローラーが実際にインターフェイスを実装している場合にのみ使用できる拡張メソッドとして設計できます。これを実現するには、 の戻り値の型はrouter.Controller、コントローラーをジェネリック パラメーターとする共変インターフェイスである必要があります。つまり、次のようなものです。

IControllerRoute<out TController>

たとえば、拡張メソッドHandlesIndexは次のように実装されます。

public static IRouteHandler HandlesIndex(
    this IControllerRoute<ISupportIndex> route)
{
    // note: This makes use of the "root" as suggested above:
    // It only specifies "index", not "/someroot/index".
    return route.Handles("index").With(x => x.Index);
}

コントローラが実際にサポートしているIControllerRoute<ISupportIndex>場合にのみ表示されます。

ブログ コントローラーのルートは次のようになります。

blog.HandlesIndex();
blog.HandlesSingleItem();

// Uses short version for models with default constructor:
blog.HandlesNew<BlogPost>().UsingFormModel();
// The version for models without default constructor could look like this:
//blog.HandlesNew<BlogPost>().UsingFormModel(() => new BlogPost(myDependency));

検証ルールを追加することも、もう少し簡潔にすることができます。

blog.HandlesNew<BlogPost>().UsingFormModel()
    .When(m => m.Status == PostStatus.New);

仕様がより複雑な場合は、 を実装する独自のクラスにパッケージ化できますIModelValidation。そのクラスが使用されるようになりました。

blog.HandlesNew<BlogPost>().UsingFormModel()
    .WithValidator<NewBlogPostValidation>();

私の提案はすべて、現在のアプローチを扱いやすくするための方法にすぎないため、これまでのところ、実際の質問には実際には答えていないと思います。私は今それをします:

コントローラーはできるだけきれいにしたい。ルートにバリデーション ルールを配置することは、私にとって非常に良いことのように思えます。コントローラー アクションは、有効なデータでのみ呼び出されると想定できるようになったからです。私はこのアプローチを続けます。

于 2013-03-01T08:28:23.080 に答える
1

はい、IMHO、ルーティングにはモデルに関するロジックやビューさえも含めるべきではありません。

現在出回っている軽量の Web フレームワーク (Nancy など) を見ると、ルーティングの概念にはビュー リンクの生成などは含まれていません。URI テンプレートをコントローラーにマッピングするだけです。これにより、ASP.NET 実装から多くの「魔法」が取り除かれます。

https://github.com/NancyFx/Nancy/wiki/Defining-routes

ただし、ナンシーのアプローチでは、利用可能なルートを理解するために「フレームワーク」コードが必要です。したがって、それはあなたの要件に正確には適合しません。

于 2013-03-01T08:05:14.147 に答える