【问题标题】:Ninject, using two way property injection to resolve cyclic dependencyNinject,使用两种方式的属性注入来解决循环依赖
【发布时间】:2013-07-25 16:30:13
【问题描述】:

基于这个问题的答案:Cyclic dependency with ninject 和这个问题:Ninject: give the parent instance to a child being resolved 这两个都说你可以使用两种方式属性注入来解决循环依赖关系,只要你将范围更改为不是默认的瞬态范围.所以我尝试这样做,我有一个UserService 和一个GroupService 需要彼此(请不要说更改课程或使用第三类等!)。我有一个通用的EntityServiceFactory,它像这样使用ninject:

public static class EntityServiceFactory
{
    public static TServiceClass GetService<TServiceClass>()
        where TServiceClass : class
    {
    IKernel kernel = new StandardKernel();
    return kernel.Get<TServiceClass>();
    }
}

还有我的服务:

public class GroupService : EntityService<GroupRepository, Group, DbContext>
{
    public UserService _userService { private get; set; }


    public GroupService(GroupRepository repository, UserService userService) : base(repository)
    {
        userService._groupService = this;
    }

public class UserService : EntityService<UserRepository, User, DbContext>
{
    public GroupService _groupService { private get; set; }

    public UserService(UserRepository repository, GroupService groupService)
        : base(repository)
    {
        groupService._userService = this;
    }

然后按照这些问题的答案中的说明将以下内容添加到我的EntityServiceFactory

kernel.Bind<GroupService>().ToSelf().InCallScope();
kernel.Bind<UserService>().ToSelf().InCallScope();

但我仍然收到错误:

在两个的构造函数之间检测到循环依赖 服务。

我是否正确地进行了双向属性注入?我该如何解决这个问题?

【问题讨论】:

  • 我不知道答案,但这是一个格式正确的问题。 +1。
  • 我知道你坚持让我们不要唠叨你的设计,但你能解释一下为什么这两个服务需要相互依赖吗?
  • 顺便说一句。 EntityServiceFactory 的使用闻起来像 Service Locator 反模式。您可能需要阅读 this article 以验证在您的应用程序中使用此模式是否会出现问题。
  • 感谢您的文章。由于我们的框架是如何使用自动生成的代码构建的,因此设计无法更改。同样由于这些类的继承链和泛型的使用,如果不复制大量不需要复制的代码,就不可能将共享逻辑提取到第三个类中。我想出了 3 种解决方案来解决这个问题,这是最容易实现的,同时也打破了最少的“标准”。

标签: c# .net dependency-injection inversion-of-control ninject


【解决方案1】:

Welp,原来我不明白我链接的问题中的答案。我根本没有做任何类似属性注入的事情,我最终做的是:

任何时候存在循环依赖,我都会从构造函数中删除其中一个循环诱导服务,并将其替换为:

    private UserService _userService;
    private UserService UserService
    {
        get { return _userService ?? (_userService = EntityServiceFactory.GetService<UserService>()); }
    }

这实际上最终非常接近于属性注入 (http://ninject.codeplex.com/wikipage?title=Injection%20Patterns)。它不像构造函数注入那样最佳,但仍然不是一个糟糕的解决方案。我也可以这样做(实际属性注入):

    private UserService _userService;
    [Inject]
    private UserService UserService
    {
        get { return _userService; }
        set { _userService = value; }
    }

我只是选择了我的方式,因为它不需要我的服务具有 ninject 特定代码,以防我改变了对它的使用,但称为 EntityServiceFactory.GetService 本质上与 [Inject] 属性做同样的事情。

【讨论】:

    猜你喜欢
    • 2013-10-01
    • 2010-11-29
    • 2019-02-17
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多