是否有在ASP.NET MVC ContactsManager教程解决了依赖注入循环问题的一个好/有

2019-07-18 18:05发布

如果你不知道我说的是要么去通过本教程 ,并尝试自己添加依赖注入或试试你的运气与我的问题的解释。

注意:这个问题是不是在ASP.NET原教程的范围之内。 本教程仅表明使用的模式是依赖注入友好。

问题基本上有控制器,所述ModelStateWrapper和ContactManagerService之间的依赖循环。

  1. ContactController中constuctor需要一个IContactManagerService。
  2. 该ContactManagerService构造函数采用IContactManagerRepository(并不重要)IValidationDictionary(其中ModelStateWrapper工具)。
  3. 所述ModelStateWrapper构造函数采用ModelStateDictionary(这是一个称为控制器上“的ModelState”属性)。

因此,依赖循环是这样的:控制器>服务> ModelStateWrapper>控制器

如果试图依赖注入添加到这一点,就会失败。 所以我的问题是; 我应该怎么办呢? 其他人张贴了这个问题,但答案是很少,不同的,似乎都有点“黑客十岁上下的”。

我目前的解决方案是从IService构造函数删除IModelStateWrapper,并添加一个初始化方法,而不是像这样:

public class ContactController : Controller
{
    private readonly IContactService _contactService;

    public ContactController(IContactService contactService)
    {
        _contactService = contactService;
        contactService.Initialize(new ModelStateWrapper(ModelState));
    }

    //Class implementation...
}

public class ContactService : IContactService
{
    private IValidationDictionary _validationDictionary;
    private readonly IContactRepository _contactRepository;

    public ContactService(IContactRepository contactRepository)
    {
        _contactRepository = contactRepository;
    }

    private void Initialize(IValidationDictionary validationDictionary)
    {
        if(validationDictionary == null)
            throw new ArgumentNullException("validationDictionary");

        _validationDictionary = validationDictionary;
    }

    //Class implementation...
}

public class ModelStateWrapper : IValidationDictionary
{
    private readonly ModelStateDictionary _modelState;

    public ModelStateWrapper(ModelStateDictionary modelState)
    {
        _modelState = modelState;
    }

    //Class implementation...
}

有了这个结构,我可以配置我的统一容器是这样的:

public static void ConfigureUnityContainer()
{
    IUnityContainer container = new UnityContainer();

    // Registrations
    container.RegisterTypeInHttpRequestLifetime<IContactRepository, EntityContactRepository>();
    container.RegisterTypeInHttpRequestLifetime<IContactService, ContactService>();

    ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory(container));
}

不幸的是,这意味着在该服务的“初始化”的方法,必须由控制器构造函数调用。 有没有更好的办法? 也许,我莫名其妙地包括在我的统一配置IValidationDictionary? 如果我切换到另一个DI容器? 我缺少的东西吗?

Answer 1:

作为一般的考虑,循环依赖表明存在设计缺陷 - 我想我可以肯定地说这一点,因为你是不是该代码原作者:)

我不会考虑的初始化方法一个很好的解决方案。 除非你有一个附加的情况下处理(你不是),注射方法是不是正确的解决方案。 你几乎已经想通了这一点,因为你觉得不满意,你需要,因为你的DI容器不能手动调用它。

除非我弄错,被调用的Action方法之前ContactController中不需要IValidationDictionary实例?

如果是这样的话,最简单的解决办法可能是定义一个IValidationDictionaryFactory接口,使的ContactController构造采取这种接口的一个实例。

此接口可以定义是这样的:

public interface IValidationDictionaryFactory
{
    IValidationDictionary Create(Controller controller);
}

这需要一个IValidationDictionary实例,然后可以调用Create方法来获得实例控制器上执行任何操作方法。

默认的实现会是这个样子:

public class DefaultValidationDictionaryFactory : IValidationDictionaryFactory
{
    public IValidationDictionary Create(Controller controller)
    {
        return controller.ModelState;
    }
}


Answer 2:

如何稍微改变/改进设计是这样的: http://forums.asp.net/t/1486130.aspx



Answer 3:

每个控制器有一个虚拟方法初始化做这样的东西。

我觉得有没有更好的办法,因为IValidationDictionary是你当前请求/控制器/ ModelState中和IContactService之间的抽象层。 注入控制器的ModelState到服务,然后注入到服务控制器使用构造注入是根本不可能的。 一个人必须第一。

可能有使用属性注入的方法吗? 但我认为这将是太复杂了。



文章来源: Is there a good/proper way of solving the dependency injection loop problem in the ASP.NET MVC ContactsManager tutorial?