ステップ 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での作業に非常に慣れているので、このフレームワークを示しますが、同じことができるフレームワーク ( Autofac、Castle Windsor、StructureMap、Ninject )が他にもたくさんあることに注意してください。
カスタム コントローラ ファクトリを記述する代わりに、次のことができます。
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
、コントローラーのコンストラクター引数を分析し、コンストラクター引数の型情報に基づいて依存関係を注入するため、代わりに を作成できます。
Profile
and を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
。あとはフレームワークがやってくれます。
やあ。パターンが好きと聞いたので、パターンにパターンを入れて、アブストラクトしながらアブストラクトできるようにしました。
