Unity - 如何避免循环引用?

时间:2013-02-14 10:10:50

标签: c# asp.net-mvc unity-container circular-reference

我正在尝试使用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不支持循环引用。这有什么(坚实的)方式。或者我应该实现不同的架构?如果是这样,你能推荐一个解决方案吗?

1 个答案:

答案 0 :(得分:1)

通常这样做的方法是只声明您需要的服务并将它们注入ctor。不要注入只包含所有内容的“ServiceWrapper”。注入你需要的东西。当容器构建您的类型时,您不必担心提供服务。他们就在那里。

开发工作流程通常如下:

  1. 添加新的依赖注入字段
  2. 删除现有的ctor
  3. 使用Resharper重新生成ctor:alt + ins,生成ctor。