我正在尝试使用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不支持循环引用。这有什么(坚实的)方式。或者我应该实现不同的架构?如果是这样,你能推荐一个解决方案吗?
答案 0 :(得分:1)
通常这样做的方法是只声明您需要的服务并将它们注入ctor。不要注入只包含所有内容的“ServiceWrapper”。注入你需要的东西。当容器构建您的类型时,您不必担心提供服务。他们就在那里。
开发工作流程通常如下: