gpt4 book ai didi

asp.net-mvc - ASP.NET MVC ContactsManager 教程中是否有解决依赖注入(inject)循环问题的好/正确方法?

转载 作者:行者123 更新时间:2023-12-02 15:02:25 25 4
gpt4 key购买 nike

如果您不知道我在说什么,请查看 the tutorial并尝试自己添加依赖注入(inject),或者尝试一下我对问题的解释。

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

问题基本上是 Controller 、ModelStateWrapper 和 ContactManagerService 之间存在依赖循环。

  1. ContactController 构造函数采用 IContactManagerService。
  2. ContactManagerService 构造函数采用 IContactManagerRepository (不重要) 和 IValidationDictionary (由 ModelStateWrapper 实现)
  3. ModelStateWrapper 构造函数采用 ModelStateDictionary(这是 Controller 上名为“ModelState”的属性)

所以依赖循环是这样的:Controller > Service > ModelStateWrapper > Controller

如果您尝试为此添加依赖注入(inject),它将失败。所以我的问题是;我该怎么办?其他人也提出了这个问题,但答案很少,各不相同,而且看起来都有点“hack-ish”。

我当前的解决方案是从 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));
}

不幸的是,这意味着服务上的“Initialize”方法必须由 Controller 构造函数手动调用。有没有更好的办法?也许我在哪里以某种方式将 IValidationDictionary 包含在我的统一配置中?我应该切换到另一个 DI 容器吗?我错过了什么吗?

最佳答案

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

我不认为初始化方法是一个好的解决方案。除非您正在处理加载项场景(您不是),否则方法注入(inject)不是正确的解决方案。您几乎已经弄清楚了这一点,因为您发现需要手动调用它并不令人满意,因为您的 DI 容器不能。

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

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

这个接口(interface)可以这样定义:

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

Controller 上任何需要 IValidationDictionary 实例的 Action 方法都可以调用 Create 方法来获取该实例。

默认实现如下所示:

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

关于asp.net-mvc - ASP.NET MVC ContactsManager 教程中是否有解决依赖注入(inject)循环问题的好/正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1453128/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com