1

MVC プロジェクト全体で多くのコントローラーを使用していますが、それらには共通点が 1 つあります。それらはすべて currentUser プロパティと currentSettings プロパティを持っています。私は次のようにDIを使用してこれを行いました:

[Authorize]
public class _UsersController : Controller
{

    #region Fields

    private readonly ProfileService service;
    private readonly Profile currentUser;
    private readonly Settings currentSettings;

    #endregion

    #region Constructors

    public _UsersController()
    {
        var companyWrapper = new CompanyWrapper();
        var profileWrapper = new ProfileWrapper();
        var settingsWrapper = new SettingsWrapper();

        var companyId = companyWrapper.CurrentCompanyId();

        service = new ProfileService(companyId);
        currentUser = profileWrapper.CurrentUser();
        currentSettings = settingsWrapper.CurrentSiteSettings();
    }

    #endregion

}

currentUser と現在の設定を保持するためのより良い方法はありますか? それを行う方法の1つは、それをカスタム AtributeFilter クラスに入れ、現在のユーザー/設定をセッションに保存することです。自分のニーズに合ったきちんとしたデザイン パターンを取得したいだけです。

4

2 に答える 2

0

ステップ 1: リージョンの使用を停止します。真剣に、それらを使用しないでください。

ステップ 2:依存性注入パターンの使用を開始します。

[Authorize]
public class _UsersController : Controller
{
    private readonly ProfileService service;
    private readonly Profile currentUser;
    private readonly Settings currentSettings;

    public _UsersController(ProfileService service, Profile currentUser, 
        Settings currentSettings)
    {
        this.service = service;
        this.currentUser = currentUser;
        this.currentSettings = currentSettings;
    }
}

_UsersController型が実際に必要とするすべての依存関係をコンストラクターに渡す (注入する) ことで、単純化しました。これらのラッパー クラスは_UsersController、これを気にする必要がないため、 から隠されています。

を作成すると、次の_UsersControllerようになります。

var companyWrapper = new CompanyWrapper();
var profileWrapper = new ProfileWrapper();
var settingsWrapper = new SettingsWrapper();

var companyId = companyWrapper.CurrentCompanyId();

var service = new ProfileService(companyId);
var currentUser = profileWrapper.CurrentUser();
var currentSettings = settingsWrapper.CurrentSiteSettings();

new _UsersController(service, currentUser, currentSettings);

そして、このコードをカスタム コントローラー ファクトリに配置する必要があります。

public class MyControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(
        RequestContext requestContext, Type controllerType)
    {
        if (controllerType == typeof(_UsersController))
        {
            // Create controller here
            new _UsersController(service, currentUser, currentSettings);
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }
}

起動時にそれを MVC に登録します。

protected void Application_Start()
{
    ControllerBuilder.Current.SetControllerFactory(typeof(MyControllerFactory));
}

ステップ 3: 関連サービスをグループ化します。

会社情報とユーザー情報は関連性が高いようです。たとえば、現在の会社は、おそらく常に現在のユーザーの会社です。複数の企業のユーザーが同時にサイトを利用している可能性があります。サイト情報は関連性が低く、展開時に修正される情報で構成されている可能性があります。状況によっては、これらのクラスをグループ化するとよい場合があります。たとえば、会社情報をプロパティとしてProfileクラスの下に配置します。

[Authorize]
public class _UsersController : Controller
{
    private readonly Profile currentUser;
    private readonly Settings currentSettings;

    public _UsersController(Profile currentUser, Settings currentSettings)
    {
        this.currentUser = currentUser;
        this.currentSettings = currentSettings;
    }
}

作成コードは次のようになります (CompanyWrapperとはクラスProfileService内に隠されています:Profile

var profileWrapper = new ProfileWrapper();
var settingsWrapper = new SettingsWrapper();

var currentUser = profileWrapper.CurrentUser();
var currentSettings = settingsWrapper.CurrentSiteSettings();

new _UsersController(currentUser, currentSettings);

ステップ 4: 依存性注入コンテナーの使用を開始します。

カスタム コントローラ ファクトリを作成するだけで問題が解決し、このクラスはすぐにメンテナンスの悪夢になります。したがって、独自のコントローラーを作成する代わりに、依存性注入フレームワークを使用できます。

私はSimple Injectorでの作業に非常に慣れているので、このフレームワークを示しますが、同じことができるフレームワーク ( AutofacCastle WindsorStructureMapNinject )が他にもたくさんあることに注意してください。

カスタム コントローラ ファクトリを記述する代わりに、次のことができます。

protected void Application_Start()
{
    var container = new Container();

    container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

    container.Register<Profile>(() => new ProfileWrapper().CurrentUser());
    container.Register<Settings>(() => new SettingsWrapper().CurrentSiteSettings());

    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}

これはSimpleInjector.MVC3 NuGet パッケージを利用します。

ProfileおよびSettingsクラスをコンテナーに登録したため_UsersController、コントローラーのコンストラクター引数を分析し、コンストラクター引数の型情報に基づいて依存関係を注入するため、代わりに を作成できます。

Profileand を1 回登録するだけSettingsで、DI フレームワークは、これらのサービスに依存するすべてのコントローラー (およびシステム内の他のすべてのクラス) にこれらの型を挿入します。

ステップ 5: 登録に適切なライフスタイルを適用します。

現在のユーザーは 1 回の Web リクエストでは変更されないため、新しいユーザーを作成して何度ProfileWrapperも呼び出す必要はありませんCurrentUser()。そのユーザー オブジェクトは、その要求の間、キャッシュできます。一方、現在のサイト設定は、アプリケーションの存続期間中はおそらく変更されないため、 を再作成しSettingsWrapperて呼び出すのCurrentSiteSettingsはばかげています。

私たちがすべきことは、これらのオブジェクトの適切なキャッシングを適用することです。これは次のように行うことができます。

container.RegisterPerWebRequest<Profile>(() => new ProfileWrapper().CurrentUser());
container.RegisterSingle<Settings>(() => new SettingsWrapper().CurrentSiteSettings());

ここで、呼び出しをRegisterからRegisterPerWebRequestおよびに変更しましたRegisterSingle。あとはフレームワークがやってくれます。

やあ。パターンが好きと聞いたので、パターンにパターンを入れて、アブストラクトしながらアブストラクトできるようにしました。

ここに画像の説明を入力

于 2013-08-29T08:22:34.083 に答える