ASP.NET MVC 3 から DI のサポートが追加されたんですが、どうも DI って好きになれなかったので放置してました。
しかし、Project Silk のソースコードを読んだのがきっかけになり、今更 DI について調べています。
とりあえず ASP.NET MVC 3 プロジェクトを作って NuGet から Unity をインストールすると使えるようにはなります。しかし、MVC 3 が提供している DI のサポートを利用するには DependencyResolver にリゾルバを追加する必要があるのですが、Unity 自体には当然ながら MVC 3 でそのまま使えるリゾルバが用意されていません。
UnityDependencyResolver で検索するといっぱいヒットしますが、一般的な IDependencyResolver の実装を載せておきます。
public class UnityDependencyResolver : IDependencyResolver { public UnityDependencyResolver(IUnityContainer container) { _container = container; } private readonly IUnityContainer _container; public object GetService(Type serviceType) { try { return _container.Resolve(serviceType); } catch { return null; } } public IEnumerable<object> GetServices(Type serviceType) { try { return _container.ResolveAll(serviceType); } catch { return null; } } }
これといった特徴のない実装です。IUnityContainer はこの後出てきます。
そしてこのリゾルバを DependencyResolver に登録してあげるといろんなところで Unity を使ったインジェクションが使えるようになります。
サンプルとしてリポジトリを登録して使えるようにしてみます。
var container = new UnityContainer(); // IProductRepository には ProductRepository を使う container.RegisterType<IProductRepository, ProductRepository>(); // リゾルバを登録 DependencyResolver.SetResolver(new UnityDependencyResolver(container));
そしてコントローラの実装です。
public class ProductController { public ProductController(IProductRepository productRepository) { _productRepository = productRepository; } private readonly IProductRepository _productRepository; public ActionResult Index() { var list = _productRepository.GetAll(); return View(list); } }
MVC 3 で開発したことのある人なら「このコードだとエラーになるのでは?」と考えると思います、Unity によってコンストラクタインジェクションが行われるので、エラーになることなく実行できます。
今まではコンストラクタを 2 つ書いていましたが、一つのコンストラクタで済むので手間が省けました。
Project Silk ではこんなもんではなく CQRS の実装などで Unity を使っているのですが、私もまだ勉強中なので今日はこのくらいにしておきたいと思います。