ニンジェクトが発砲してない?
-
22-07-2019 - |
質問
初めて Ninject をセットアップしようとしています。IRepository インターフェイスと Repository 実装があります。私はASP.NET MVCを使用しており、次のように実装を注入しようとしています。
public class HomeController : Controller
{
[Inject] public IRepository<BlogPost> _repo { get; set; }
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
var b = new BlogPost
{
Title = "My First Blog Post!",
PostedDate = DateTime.Now,
Content = "Some text"
};
_repo.Insert(b);
return View();
}
// ... etc
}
Global.asax は次のとおりです。
public class MvcApplication : NinjectHttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
protected override void OnApplicationStarted()
{
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(new BaseModule());
return (kernel);
}
}
BaseModule クラスは次のとおりです。
public class BaseModule : StandardModule
{
public override void Load()
{
Bind<IRepository<BlogPost>>().To<Repository<BlogPost>>();
}
}
ただし、Index() アクションを参照して _repo.Insert(b) を使用しようとすると、「オブジェクト参照がオブジェクトのインスタンスに設定されていません」というメッセージが表示されます。私は何を省略しているのでしょうか?
解決
Ninject 1.0 には、そのままでは MVC サポートがありませんでした。Ninject 1.0 で MVC を使用するさまざまな方法が Web 上に散在しています。
MVC サポートを含む最新のコードを Ninject トランクから入手することをお勧めします。次に、アプリケーションの開始点として以下を使用します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using DemoApp.Models;
using Ninject.Core;
using Ninject.Framework.Mvc;
namespace DemoApp
{
public class MvcApplication : NinjectHttpApplication
{
protected override void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new BaseModule(), new AutoControllerModule(Assembly.GetExecutingAssembly()));
}
}
}
元の実装と比較して強調すべき点がいくつかあります...
- ニンジェクトは 二実装名はninjecthttpapplication -on ninject.framework.web、1つはninject.framework.mvcにあります。前者は保護されたRegisterRoutes()メソッドが含まれているため、前者を使用しているように見えます。
- Ninject にコントローラー作成へのフックを与える方法が必要です。これは、ControllerBuilder を使用して行われます。Ninject.Framework.Mvc.NinjectHttpApplication は NinjectControllerFactory を登録します。Ninject 1.0 を使用する場合は、自分で提供する必要があります。
- コントローラーをコンテナーに登録する必要があります。手動で行うこともできますが、最新のコードを使用すると、コントローラーを自動的に登録する AutoControllerModule が提供されます。
他のヒント
カーネルを作成するときに指定するモジュールのリストに、 AutoControllerModule を追加する必要があります。
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel(
new BaseModule(),
new AutoControllerModule(Assembly.GetExecutingAssembly())
);
return (kernel);
}
AutoControllerModule は、Ninject 1.xのMVCサポートの一部です。 MVCコントローラークラスのコンストラクターに指定したアセンブリをスキャンし、それらを自動バインドします。コードでは、リポジトリを適切にバインドしていますが、Ninjectはコントローラーのアクティベーションを担当していません。リポジトリを HomeController クラスのインスタンスに挿入するには、Ninjectがコントローラーの作成とアクティブ化を担当する必要があります。 AutoControllerModule がない場合、MVCはコントローラーの作成を担当します。したがって、Ninjectはメンバーを注入する機会を得ることはありません。 Ninjectがコントローラーの作成とアクティブ化を担当すると、予想どおりに注入が行われます。
AutoControllerModule は、すべてのコントローラーを検索し、次のようなコードを生成すると考えてください(例としてHomeControllerを使用):
Bind<HomeController>.ToSelf();