我想知道我的解决方案中是否存在设计缺陷。这是我所拥有的:
-
Entities
=> 纯波科。 参考文献:无。 -
Data
=> 数据访问。 参考:Entities
. -
Service
=>业务逻辑。 参考:Entities
和Data
- 经理类。
- 视图模型。
-
WebApp
=> UI。参考:Entities
和Service
WebApp
ASP.NET MVC 项目作为 UI,Entities
没有用于持有纯 POCO 的参考的项目。 Data
访问业务逻辑的数据库和Service
(我的经理类所在的位置)。
基本上,我已经为每个实体定义了一个Manager
类。例如,我有一个与Recipient
实体列表相关的Message
实体。我有一个MessageManager
和RecipientManager
类,负责使用数据层和逻辑结果的 CRUD 操作(例如 public List<Message> GetAllMessagesWithPermissionForUser(User user, Permission permission)
)
对于我的 MVC 项目,我在服务层中定义了一些 ViewModel 类,以便为我的视图生成特定的视频模型。由于视图模型使用的是管理器类,因此我在服务类中定义了它们。例如,我有一个具有PermittedBoxesToSend
属性的MessageOperationVM
视图模型。此属性使用 my BoxManager
类来获取指定消息允许的所有框:
// Initialized by Catsle Windsor.
public BoxManager BoxManager {get; set;}
public List<Box> PermittedBoxesToSend
{
if(this._premittedBoxesToSend != null)
{
this._permittedBoxesToSend = BoxManager.GetPermittedBoxesToSend(this.Message);
}
}
我不确定在视图模型中使用管理器类是否是一个好的设计。尽管我已经将它们定义为构造函数/属性设置器以填充 DI。我是否应该在控制器中填充视图模型的属性,而不是定义属性并摆脱视图模型中的管理器类?
public ActionResult ShowNewMessageDialog() { var messageVM = new MessageOperationVM() { new Message() }; messageVM = this.BoxManager.GetPermittedBoxesToSend(); }
为每个实体使用管理器类似乎使维护变得困难。(尽管它们都派生自一个共享它们共同操作的
BaseManager
类)- 在上面的设计中有什么值得一提的重新考虑吗?
谢谢。
更新:
基于EulerFX的回答:
我对你的回答的问题是:要构造一个视图模型,我必须调用一些服务层的方法。所以我不能仅仅基于我的poco实体来构建我的视图模型。您是否建议我也应该在控制器中构建这些部分?:
public ActionResult ShowNewMessageDialog()
{
var message = this.messageRepository.GetMessage();
var messageVM = new MessageViewModel(message);
messageVM.CustomProperty = this.messageManager.CallSomeMethod(message);
return View(messageVM);
}
我认为从视图模型到服务的引用是一个设计缺陷。视图模型应该是平面和简单的 DTO,旨在与视图绑定。它们不应该是 DI 容器图的一部分,因为这会使事情复杂化,并使代码推理更加困难。您正在使用的术语的接受定义如下。
- 实体
- 是您所描述的实体。它们是简单的 POCO 类。
- 您所说的"数据"是存储库模式。存储库提供对基础数据库中实体的访问和持久性。
- 服务是一个重载术语,但它们通常用于封装域,将其作为 API 公开给其他应用程序层。服务可以引用存储库。我在 DDD 上下文中写了一篇关于这些类型的服务的博客文章,它们被称为应用程序服务。
- 视图模型是表示层或 WebUI 的一部分。因此,它们由 MVC 控制器构造并传递到视图。控制器使用从应用程序服务或直接从存储库获取的数据构建视图模型。视图模型可以包含一个构造函数,该构造函数接受服务或存储库返回的实体。
代码可能如下所示:
/// Domain model class that lives in domain/business layer project
public class Message
{
// properties and behavior go here
}
// View model class that lives in the ASP.NET project
public class MessageViewModel
{
public MessageViewModel() { }
public MessageViewModel(Message message)
{
// construct the view model based on the provided entity
}
// properties specific to the view go here
}
// ASP.NET MVC controller.
public class MessagesController : Controller
{
// this repository should be injected by DI container.
readonly IMessageRepository messageRepository;
public ActionResult ShowNewMessageDialog()
{
var message = this.messageRepository.GetMessage();
return View(new MessageViewModel(message));
}
}
您可以考虑使用 Visitor
设计模式来操作 Entities
和 Data
类,而不是管理器类。
如果 Manager
或 Visitor
类的定义使得它们不必仅在 View 代码中使用,那么这应该不是问题。但是,如果它们只能在视图中使用,而对于其他视图等,您必须重新定义对Entities
和Data
类的访问,或者编写更多/重复的代码,那么这是有问题的。