asp.net-mvc – 在ASP.NET MVC ContactsManager教程中是否有一个很好/适当的方法来解决依赖注入循环问题?

如果你不知道我在说什么,要么通过 the tutorial,并尝试添加依赖注入自己或尝试你的运气与我的问题的解释。

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

问题基本上是在Controller,ModelStateWrapper和ContactManagerService之间有一个依赖循环。

> ContactController构造器需要一个IContactManagerService。
> ContactManagerService构造函数接受一个I​​ContactManagerRepository(不重要)和一个IValidationDictionary(ModelStateWrapper实现的)。
> ModelStateWrapper构造函数接受一个ModelStateDictionary(它是控制器上的一个名为“ModelState”的属性)。

所以依赖循环如下所示:Controller>服务> ModelStateWrapper>控制器

如果您尝试添加依赖注入,它将失败。所以我的问题是我该怎么办?其他人已经发布了这个问题,但答案很少,不同,而且似乎都是“黑客”。

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

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容器吗?我缺少什么?

解决方法

作为一般考虑,循环依赖表示设计缺陷 – 我想我可以安全地说这个,因为你不是代码的原始作者:)

我不会认为Initialize方法一个很好的解决方案。除非您处理附加情况(您不是),否则方法注入不是正确的解决方案。你几乎已经知道了,因为你发现不方便你需要手动调用它,因为你的DI容器不能。

除非我完全错误,否则ContactController在调用Action方法之前不需要IValidationDictionary实例?

如果这是真的,最简单的解决方案可能是定义一个IValidationDictionaryFactory接口,并使ContactController构造函数接受此接口的实例。

这个接口可以这样定义:

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

需要IValidationDictionary实例的控制器上的任何Action方法都可以调用Create方法获取实例。

认实现将如下所示:

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

相关文章

这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识...
Some samples are below for ASP.Net web form controls:(fr...
问题描述: 对于未定义为 System.String 的列,唯一有效的值...
最近用到了CalendarExtender,结果不知道为什么发生了错位,...
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence cha...