Unity を使用して ASP.NET MVC プロジェクトに依存性注入を実装しようとしていますが、循環参照を回避する方法についてアドバイスが必要です。
私の職場では、アプリケーションの個々のサービスごとにシングルトンを返すサービス ロケーター パターンを実装していました。
public class ServiceWrapper
{
private UserService _userService;
private ProductService _productService;
public UserService User
{
if(_userService == null)
{
_userService = new UserService();
}
return _userService;
}
public ProductService Product
{
if(_productService == null)
{
_productService = new ProductService();
}
return _productService;
}
}
次に、コントローラーで ServiceWrapper をインスタンス化し、次のようなメソッドを呼び出すことで、すべてのサービスに簡単にアクセスできます。
private ServiceWrapper _services = new ServiceWrapper();
public ActionResult Index()
{
List<Product> products = _services.Product.GetProducts();
return View(products);
}
Unity を使用した DI のセットアップは簡単でした。次のように、Application_Start() (global.asax) でコンテナーを作成しました。
var container = new UnityContainer();
container.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
container.RegisterType<IServiceWrapper, ServiceWrapper>(new ContainerControlledLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
ServiceWrapper は Singleton として登録されます。そして、次のようにコンストラクター注入を実装しました。
public class ProductController: Controller
{
private IServiceWrapper _services;
public ProductController(IServiceWrapper services)
{
_services = services;
}
public ActionResult Index()
{
List<Product> products = _services.Products.GetProducts();
return View(products);
}
それは見事に機能しました。しかし、その後、問題に遭遇しました。
次のように、別の 内から他のサービスに簡単にアクセスできるように、すべてのサービスに ServiceWrapper を含むプロパティも用意することをお勧めします。
public class ProductService
{
private IServiceWrapper _services;
public ProductService(IServiceWrapper services)
{
_services = services;
}
public IServiceWrapper Services { get { return _services; } }
}
しかし、個々のサービスで ServiceWrapper のコンストラクター インジェクションを実装すると、循環参照が原因でスタック オーバーフロー例外が発生しました。
Unity は循環参照をサポートしていないことを読みました。これを回避する(堅実な)方法はありますか。または、別のアーキテクチャを実装する必要がありますか? もしそうなら、解決策をお勧めできますか?