在ViewModels中使用服务层类。设计缺陷?

时间:2012-04-24 07:13:22

标签: design-patterns domain-driven-design viewmodel

我想知道我的解决方案是否存在设计缺陷。这就是我所拥有的:

  • Entities =>纯poco。 refs:none。
  • Data =>数据访问。参考:Entities
  • Service =>商业逻辑。参考:EntitiesData
    • 经理课程。
    • 的ViewModels。
  • WebApp => UI。参考:EntitiesService

WebApp ASP.NET MVC项目作为UI,Entities项目没有参考来保存纯POCO。 Data访问数据库,Service访问Business Logic(我的Manager类所在的位置)。

基本上,我为每个实体定义了一个Manager类。例如,我有一个与Message实体列表相关的Recipient实体。我有一个MessageManagerRecipientManager类,负责使用数据层和逻辑结果的CRUD操作(例如public List<Message> GetAllMessagesWithPermissionForUser(User user, Permission permission)

对于我的MVC项目,我在Service层中定义了一些ViewModel类,为我的视图生成特定的视频模型。由于视图模型使用的是Manager类,因此我在我的服务类中定义了它们。例如,我有一个MessageOperationVM视图模型,它具有PermittedBoxesToSend属性。此属性使用我的BoxManager类来获取指定消息允许的所有框:

// Initialized by Catsle Windsor.
public BoxManager BoxManager {get; set;}

public List<Box> PermittedBoxesToSend 
{
    if(this._premittedBoxesToSend != null)
    {
        this._permittedBoxesToSend = BoxManager.GetPermittedBoxesToSend(this.Message);
    }
}
  • 我不确定在Viewmodels中使用管理器类是否是一个好的设计。虽然我已经将它们定义为构造函数/属性setter以填充DI。我应该在控制器中填充我的viewmodels属性而不是定义属性并在我的ViewModels中删除管理器类吗?

    public ActionResult ShowNewMessageDialog()
    { 
        var messageVM = new MessageOperationVM() { new Message() };
        messageVM = this.BoxManager.GetPermittedBoxesToSend();
    }
    
  • 为每个实体使用经理类似乎使维护变得困难。 (虽然它们都来自BaseManager类,它们共享它们共同的操作)

  • 在上述设计中是否有任何值得一提的重新考虑?

谢谢。

更新
基于eulerfx的回答:
我的回答是:要构建一个ViewModel,我必须调用一些服务层的方法。所以我不能仅仅根据我的poco实体构建我的ViewModel。你是否建议我也应该在控制器中构建这些部件? :

public ActionResult ShowNewMessageDialog()
{
    var message = this.messageRepository.GetMessage();
    var messageVM = new MessageViewModel(message);
    messageVM.CustomProperty = this.messageManager.CallSomeMethod(message);
    return View(messageVM);
}

2 个答案:

答案 0 :(得分:9)

我会考虑视图模型中的引用来为设计缺陷提供服务。视图模型应该是扁平的,简单的DTO用于与视图绑定。它们不应该是DI容器图的一部分,因为这会使事情复杂化并使代码的推理变得更加困难。您使用的术语的可接受定义如下。

  • Entites是您描述的实体。它们是简单的POCO类。
  • 您所谓的“数据”是repository pattern。存储库提供对底层数据库中实体的访问和持久性。
  • 服务是一个重载术语,但它们通常用于封装域,将其作为API暴露给其他应用程序层。服务可以引用存储库。我在DDD here的上下文中写了一篇关于这些类型服务的博客文章,它们被称为应用程序服务。
  • 视图模型是您调用它的表示层或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));
 }
}

答案 1 :(得分:1)

您可以考虑使用Visitor设计模式来操作EntitiesData类,而不是Manager类。

如果ManagerVisitor类定义为不必仅在View代码中使用,那么它不应该是一个问题。但是,如果它们只能在视图和其他视图等中使用,则必须重新定义对EntitiesData类的访问权限,或者编写更多/重复的代码,然后才会出现问题。< / p>

相关问题