gpt4 book ai didi

c# - DI 组合根 : how does it ensure compile-time resolution checking

转载 作者:行者123 更新时间:2023-11-30 20:40:28 26 4
gpt4 key购买 nike

我读了几篇我的 Mark Seeman 关于依赖注入(inject)的文章,特别是避免服务定位器模式的原因:

Service Locator 存在问题的基本思想是它可能在运行时失败:

public class OrderProcessor : IOrderProcessor
{
public void Process(Order order)
{
var validator = Locator.Resolve<IOrderValidator>();
if (validator.Validate(order))
{
var shipper = Locator.Resolve<IOrderShipper>();
shipper.Ship(order);
}
}
}

var orderProcessor = new OrderProcessor();

// following line fails at compile time if you
// forget to register all necessary services - and
// you don't have a way of knowing which services it needs

orderProcessor.Process(someOrder);

但这意味着 Composition Root 不仅必须在启动时解析所有 依赖关系,而且实际上实例化整个对象图,否则我们仍然不知道所有必要的依赖关系都已注册:

private static void Main(string[] args)
{
var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(
new CollectionResolver(container.Kernel));

// Register
container.Register(
Component.For<IParser>()
.ImplementedBy<WineInformationParser>(),
Component.For<IParser>()
.ImplementedBy<HelpParser>(),
Component.For<IParseService>()
.ImplementedBy<CoalescingParserSelector>(),
Component.For<IWineRepository>()
.ImplementedBy<SqlWineRepository>(),
Component.For<IMessageWriter>()
.ImplementedBy<ConsoleMessageWriter>());

// Everything must be resolved AND instantiated here
var ps = container.Resolve<IParseService>();
ps.Parse(args).CreateCommand().Execute();

// Release
container.Release(ps);
container.Dispose();
}

这在实际应用中的可行性如何?这是否真的意味着您不应该在构造函数之外的任何地方实例化任何东西?

(附加信息)

假设您有一项服务应该处理来自某种类型的多个测量设备(不同的连接类型、协议(protocol)或同一协议(protocol)的不同版本)的传入连接。每当您获得新连接时,服务都应该从输入端口构建一个“管道”,通过 fifo 缓冲区,到许多特定于该设备类型的解析器,以多个消费者结束各种解析消息。

提前组合这些对象图在应用程序启动时似乎是不可能的。即使它可以延迟,我仍然看不出如何获得对象图构造将失败的早期(-er)指示

这似乎是 main problem with service locators ,我不知道如何避免它:

In short, the problem with Service Locator is that it hides a class' dependencies, causing run-time errors instead of compile-time errors, as well as making the code more difficult to maintain because it becomes unclear when you would be introducing a breaking change.

最佳答案

But this means that the Composition Root must not only resolve all dependencies at startup, but actually instantiate the entire object graph

如果你申请Pure DI (即应用依赖注入(inject)模式,但没有 DI 容器)您将获得开箱即用的编译时支持。对于 DI 容器,您必须在运行时进行这些检查,但这并不意味着您必须在启动期间进行这些检查,尽管我认为这是首选。因此,如果在启动时检查容器的配置不会导致性能问题,那么您应该这样做。否则,您可以将此验证步骤移至单元测试。

How feasible is this in a real world application?

这是完全可行的。我构建的大型应用程序通常在容器中注册了数百到一千多个服务,并且我始终验证(和 diagnose)我的容器配置,这可以防止许多常见的配置错误,这些错误很容易犯,而且很难追踪。

Does this really mean you are not supposed to instantiate anything anywhere outside the constructor?

负责创建服务的是您的组合根;这本身并不意味着所有服务都应在启动期间创建,因为您可以将部分对象图的创建延迟到运行时。然而,我更喜欢的工作方式是使所有注册服务成为单例(一个实例用于应用程序期间)。这使得在应用程序启动期间创建所有服务变得非常容易(而且成本低廉),并迫使您进入一个更严格的模型,在该模型中,SOLID 违规和其他 DI 不良做法会更快弹出。

关于c# - DI 组合根 : how does it ensure compile-time resolution checking,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33364761/

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