使用 IoC 容器时如何管理接口隔离?
我'我目前正在设计一个小型系统,并且正在使用 StructureMap 作为 IoC。我最近刚刚明白了接口隔离的要点……我现在想知道。
如果我有一个特定的业务对象,它将实现三个接口......我应该如何在代码的配置和实例化中处理这个问题?
假设我在一个简单的场景中有两个接口,用于名为 EmployeeServiceObject 的服务层类。 IGenericEntity 和 IEmployeeServiceObject。
GenericEntity将为该类提供CRUD功能,IEmployeeServiceObject将为业务查询/操作提供结果集。
如果在外观/服务层方法上,我必须使用 EmployeeServiceObject 类并实际使用两个接口的功能...应该如何处理?
最初我认为正确的做法是设置 IoC 的配置以将 IEmployeeServiceObject 映射到 EmployeeServiceObject,向工厂询问该对象,然后在需要使用 CRUD 功能时将其强制转换为 IGenericEntity,但我不太确定。这似乎也不正确,因为我从未正式声明具体类实际上实现了 ioc 容器配置中未设置的接口。
我绝对知道创建同一个具体类的两个实例但要求不同的接口......听起来更糟糕。
这应该如何处理?
Possible Duplicate:
StructureMap singleton usage (A class implementing two interface)
I'm currently designing a small system and i'm currently using structureMap as IoC. I just recently got the point of interface segregation...and I'm wondering now.
If I have a certain business object, that will implement say, three interfaces... how should I handle this in the configuration and instatiation of code?
Assuming I have two interfaces in a simple scenario, for a service layer class called EmployeeServiceObject. IGenericEntity and IEmployeeServiceObject.
GenericEntity will provide the CRUD capabilities for the class, and IEmployeeServiceObject will provide resultsets for business queries/operations.
If on a Facade/Service Layer method, I have to use the EmployeeServiceObject class and actually use functionality from both interfaces...how should this be handled?
Initially I thought that the correct thing was to setup the configuration of the IoC to map IEmployeeServiceObject to EmployeeServiceObject, ask the factory for the object, and just cast it to IGenericEntity when i needed to use the CRUD functionality, but i'm not quite sure. It also does not seem right because I'd never be formally stating that the concrete class is actually implementing the interface that was not setup in the ioc container configuration.
and I definitely know that creating two instances of the same concrete class but asking for a different interface...sounds even worse.
How should this be handled?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果我正确理解了这个问题,您将看到以下场景(在 C# 代码中):
如果是这样,那么 EmployeeServiceObject 实现这两个接口的事实就是一个实现细节。您可能有其他单独实现每个接口的实现。
ISP 的要点是每个接口都建模一个单独的关注点,因此,如果您经常发现自己处于同时需要 IGenericEntity 和 IEmployeeServiceObject 的情况,您应该质疑分成两个接口是否有意义。
否则,您应该单独请求每个接口,因为任何尝试转换都会违反里氏替换原则 。
如果您确实需要这两个接口,则需要同时请求这两个接口:
如果您有一个类 (EployeeServiceObject) 实现这两个接口,则您需要告诉 DI 容器是这种情况。此时,我们将进入特定于容器的详细信息区域,因此您如何执行此操作因每个容器而异。
例如,Windsor 具有 Forward 方法,可让您指定将一个接口的请求转发到另一种类型。
在Poor Man's DI中,它非常简单,因为
了解如何使用Poor Man's DI构建依赖层次结构总是一件好事,因为它可以为您提供有价值的线索,让您了解容器如何理解同一事物。
If I understand the question correctly, you have the following scenario (in C# code):
If so, the fact that EmployeeServiceObject implements both interfaces is an implementation detail. You may have other implementations that implement each interface separately.
The point of the ISP is that each interface models a separate concern, so if you often find yourself in a situation where you need both IGenericEntity and IEmployeeServiceObject you should question whether the separation into two interfaces is meaningful.
Otherwise you should request each interface separately, because any attempt at casting would be breaking the Liskov Substitution Principle.
In the cases where you truly need both, you will need to request both:
In the case where you have one class (EployeeServiceObject) implementing both interfaces, you will need to tell the DI Container that this is the case. At this point, we are moving in to the area of container-specific details, so how you do that varies with each container.
For example, Windsor has the Forward method that lets you specify that requests for one interface is forwarded to another type.
In Poor Man's DI it's as simple as
It's always a good thing to understand how you would compose the dependency hierarchy with Poor Man's DI because it can give you valuable clues to how the container would understand the same thing.
如果可以的话,在讨论 DI/IoC 实现之前,我想先讨论一下你们的 API。我认为你的痛点正在试图引导你做出更好的设计。
EmployeeServiceObject 似乎有太多的职责。创建对象时请考虑单一职责原则。在您的描述中,EmployeeServiceObject 既是外观/服务层又是 CRUD 层。通过分配 CRUD 操作的接口 (IGenericEntity),您可以将 CRUD 实现公开给外观的使用者 (IEmployeeServiceObject)。
鉴于您所描述的这种情况和类型,请考虑采用不同的方法(我还会重新考虑您的类型名称以更准确地描述其用途):
将 IEmployeeServiceObject/EmployeeServiceObject 和 IGenericEntity/GenericEntity 对注册为您选择的容器。 (StructureMap 可以按照约定注册这些类型。)
当您从容器请求 IEmployeeServiceObject 时,容器会将 GenericEntity 注入到 EmployeeServiceObject 的构造函数中,然后再将其提供给您。
通过这种方式,您可以避免您所描述的铸造/注册问题。无需强制容器以次优方式工作。另外,您的外观仅公开其客户端所需的内容,并将 CRUD 操作推迟到另一个类(不需要公开给客户端)。
If I may, before addressing the DI/IoC implementation, I would like to address your API. I think your pain points are trying to lead you to a better design.
The EmployeeServiceObject seems to have too many responsibilities. Consider the Single Responsibility Principle while creating your objects. In your description, the EmployeeServiceObject is both a facade/service layer and a CRUD layer. By assigning the interface for the CRUD operations(IGenericEntity), you are exposing your CRUD implementation to the consumer of your facade(IEmployeeServiceObject).
Given this situation and types you've described, please consider a different approach (I would also reconsider your type names to more accurately describe their purpose):
Register the IEmployeeServiceObject/EmployeeServiceObject and the IGenericEntity/GenericEntity pairs with your container of choice. (StructureMap can register these types by convention.)
When you request the IEmployeeServiceObject from the container, the container will inject the GenericEntity into the EmployeeServiceObject's constructor prior to giving it to you.
In this way, you avoid the casting/registration issues you described. There is no need to force the container to work in a sub-optimal manner. Plus, your facade only exposes what is needed by its clients, and defers CRUD operations to another class (which does not need to be exposed to the clients).
我没有找到如何将我的问题作为重复项关闭...但我在另一个 stackoverflow 问题中确切地找到了如何做我需要做的事情。
Mark 在 Windsor 中提到的 Forward 方法,它也存在于 StructureMap 中……而且看起来这将是正确的做事方式。
StructureMap 单例用法(实现两个接口的类)
I didnt find how to close my question as duplicate...but I found exactly how to do what I needed in another stackoverflow question.
What Mark mentioned as the Forward method in Windsor, it also exists in StructureMap...and it appears it would be the right way to do things.
StructureMap singleton usage (A class implementing two interface)