使用 Autofac 进行 IoC

发布于 2024-10-06 07:04:10 字数 446 浏览 0 评论 0原文

我刚刚开始使用 IoC 框架,并且一直在使用 Autofac。

在下面的示例代码中,我注册了两个完全不同的类(在 global.asax 中),它们都实现了相同的接口,我想知道我们如何确保 Autofac 使用正确的类?目前,我的一个控制器采用 IPhotoBlogRepository 作为其构造函数,传递的是 PhotoBlogRepositoryTestRepository,具体取决于下面代码中第一个/最后出现的一个。

builder.RegisterType<PhotoBlogRepository>().As<IPhotoBlogRepository>();
builder.RegisterType<TestRepository>().As<IPhotoBlogRepository>();

I'm just starting out with IoC frameworks and have been playing with Autofac.

In the following example code where I am registering 2 completely different classes (in global.asax) that both implement the same interface, I am wondering how we ensure the correct one is used by Autofac? At present, one of my controller's that takes an IPhotoBlogRepository as its constructor, is passed either a PhotoBlogRepository OR a TestRepository, depending on which appears first/last in the below code.

builder.RegisterType<PhotoBlogRepository>().As<IPhotoBlogRepository>();
builder.RegisterType<TestRepository>().As<IPhotoBlogRepository>();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

待"谢繁草 2024-10-13 07:04:10

这是设计使然。容器无法立即知道您想要哪种服务。如果在生产代码中只有一种接口实现,那么您的注册代码应确保注册的服务不超过一项。

如果您打算支持多种实现,那么您的控制器可以依赖 IEnumerable。 Autofac 将为控制器提供实现该接口的所有已注册服务的集合。

如果控制器需要更细粒度的控制,请查看 Autofac 如何支持元数据。

也就是说:从您的示例中我看到您正在注册该接口的测试实现。在单元测试中,我很少从容器中解析 SUT(本例中为您的控制器),而是直接实例化它。这消除了用假服务“替换”真实服务的问题,因为您总是将它们直接交给控制器构造函数。

This is by design. A container cannot out of the box know which service you intended. If in production code there will only be one implementation of the interface, then your registration code should make sure that no more than one service is registered.

If you intend to support multiple implementations, then your controller could take a dependency on IEnumerable<IPhotoBlogRepository>. Autofac will give the controller a collection of all registered services implementing that interface.

If the controller need even more fine-grained control, take a look at how Autofac supports metadata.

That said: from your sample I see that you are registering a test implementation of the interface. In unit tests I seldom resolve the SUT (your controller in this case) from a container, but rather instantiate it directly. This eliminates the problem of "replacing" real services with fake ones since you will always hand them directly to the controller constructor.

网白 2024-10-13 07:04:10

如上所述,元数据可能是您想要的方式,但如果您只想确保选择第一个实现,那么您应该使用 PreserveExistingDefaults() 进行所有其他注册即:

builder.RegisterType<PhotoBlogRepository>().As<IPhotoBlogRepository>();
builder.RegisterType<TestRepository>().As<IPhotoBlogRepository>().PreserveExistingDefaults();

最后一个注册将被选为默认注册,而不应用 PreserveExistingDefaults()

As pointed out above, metadata is probably the way you want to go with this, but if you just want to simply ensure that the first implementation is chosen then you should use PreserveExistingDefaults() for all the additional registrations i.e.:

builder.RegisterType<PhotoBlogRepository>().As<IPhotoBlogRepository>();
builder.RegisterType<TestRepository>().As<IPhotoBlogRepository>().PreserveExistingDefaults();

The last registration is the one which will be chosen as the default without applying PreserveExistingDefaults().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文