C# 基类(域模型)到派生类(视图模型)的转换

C# 基类(域模型)到派生类(视图模型)的转换,c#,asp.net-mvc-3,C#,Asp.net Mvc 3,我在MVC应用程序中看到以下模式,其中基本上派生类向域类添加了次要功能,很多时候只是显示依赖于基类中其他属性的只读属性。不必编写非常基本的属性复制代码(between//*****/*****)的更好方法是什么 编辑:我想通过这个问题来解决在应用程序中传播太多“属性复制”代码的问题。不幸的是,错误的示例选择(源自DomainModel的ViewModel)导致了另一个领域的讨论。在基础中创建一个副本构造函数 这将在派生类中为您节省大量代码 public class MyDomainModel {

我在MVC应用程序中看到以下模式,其中基本上派生类向域类添加了次要功能,很多时候只是显示依赖于基类中其他属性的只读属性。不必编写非常基本的属性复制代码(
between//*****/*****
)的更好方法是什么


编辑:我想通过这个问题来解决在应用程序中传播太多“属性复制”代码的问题。不幸的是,错误的示例选择(源自DomainModel的ViewModel)导致了另一个领域的讨论。

在基础中创建一个副本构造函数

这将在派生类中为您节省大量代码

public class MyDomainModel
{
    public bool BoolValue { get; set; }

    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public MyDomainModel(MyDomainModel myDomainModel)
    {
        var myViewModel = new MyViewModel();

        //*****
        this.BoolValue = myDomainModel.BoolValue;
        this.Prop1 = myDomainModel.Prop1;
        this.Prop2 = myDomainModel.Prop2;
        // Several other properties
        //*****
    }
}

public class MyViewModel : MyDomainModel
{
    // This is the only property that is added to the view model class
    public string DisplayValue
    {
        get { return BoolValue ? "Value1" : "Value2"; }
    }

    public MyViewModel (MyDomainModel other) : base(other) {}
}
然后在代码中使用:

// some other place

MyDomainModel myDomainObject = CallService();

//Here MyDomainModel needs to be converted to MyViewModel
MyViewModel myViewObject = new MyViewModel(myDomainObject);

在基中创建一个副本构造函数

这将在派生类中为您节省大量代码

public class MyDomainModel
{
    public bool BoolValue { get; set; }

    public string Prop1 { get; set; }
    public int Prop2 { get; set; }

    public MyDomainModel(MyDomainModel myDomainModel)
    {
        var myViewModel = new MyViewModel();

        //*****
        this.BoolValue = myDomainModel.BoolValue;
        this.Prop1 = myDomainModel.Prop1;
        this.Prop2 = myDomainModel.Prop2;
        // Several other properties
        //*****
    }
}

public class MyViewModel : MyDomainModel
{
    // This is the only property that is added to the view model class
    public string DisplayValue
    {
        get { return BoolValue ? "Value1" : "Value2"; }
    }

    public MyViewModel (MyDomainModel other) : base(other) {}
}
然后在代码中使用:

// some other place

MyDomainModel myDomainObject = CallService();

//Here MyDomainModel needs to be converted to MyViewModel
MyViewModel myViewObject = new MyViewModel(myDomainObject);

这类似于在渲染视图之前要将信息附加到所有模型的模式。实际上,您可以通过重写OnActionExecuted,然后将数据附加到模型来实现这一点

 protected override OnActionExecuted(ActionExecutedContext context)
 {
      ViewResult viewResult = filterContext.Result as ViewResult;

      if(viewResult != null)
      {
           MyDomainModel model = viewResult.ViewData.Model as MyDomainModel;

           if(model != null)
              /* Set Properties on your Model, for any model deriving 
                 from MyDomainModel! */
      }
 } 

这类似于在渲染视图之前要将信息附加到所有模型的模式。实际上,您可以通过重写OnActionExecuted,然后将数据附加到模型来实现这一点

 protected override OnActionExecuted(ActionExecutedContext context)
 {
      ViewResult viewResult = filterContext.Result as ViewResult;

      if(viewResult != null)
      {
           MyDomainModel model = viewResult.ViewData.Model as MyDomainModel;

           if(model != null)
              /* Set Properties on your Model, for any model deriving 
                 from MyDomainModel! */
      }
 } 
为什么要让视图模型继承域模型这似乎是个糟糕的主意。

在这种情况下,继承给你什么好处?你在用什么

我所能看到的只是一包属性,在您的使用场景中,您甚至不能重用这些属性(因为您得到了一个已经实例化的基类,并且您不能将其实例化为派生类)

这里(通常)有一条公理似乎是合适的,那就是“偏爱组合而非继承”。除非你有明确的理由和继承的好处,否则要避免

最常见的建议是使ViewModels完全独立于类,并保持它们不依赖。它们应该是简单的POCO

然后,只需将域模型对象映射到视图模型对象。这将涉及一些重复的属性复制代码或使用像AutoMapper这样的工具,但您希望在这里进行复制,因为这会减少耦合

另一方面,继承引入了一些非常紧密的耦合,这几乎肯定会给您带来问题

为什么要让视图模型继承域模型这似乎是个糟糕的主意。

在这种情况下,继承给你什么好处?你在用什么

我所能看到的只是一包属性,在您的使用场景中,您甚至不能重用这些属性(因为您得到了一个已经实例化的基类,并且您不能将其实例化为派生类)

这里(通常)有一条公理似乎是合适的,那就是“偏爱组合而非继承”。除非你有明确的理由和继承的好处,否则要避免

最常见的建议是使ViewModels完全独立于类,并保持它们不依赖。它们应该是简单的POCO

然后,只需将域模型对象映射到视图模型对象。这将涉及一些重复的属性复制代码或使用像AutoMapper这样的工具,但您希望在这里进行复制,因为这会减少耦合


另一方面,,引入了一些非常紧密的耦合,这几乎肯定会给您带来问题。

我认为您违反了单一责任原则,因为ViewModel的责任只是将域模型中的一些数据呈现给视图,而不使用该类视图模型类通常表示的任何业务逻辑 一个DTO对象,您可以使用

看看下面的文章和例子


我认为您违反了单一责任原则,因为ViewModel的责任只是将域模型中的一些数据呈现给视图,而不使用该类视图中的任何业务逻辑。模型类通常表示 一个DTO对象,您可以使用

看看下面的文章和例子


那么,您应该如何准确地实例化一个用现有的
MyDomainModel
填充的
MyViewModel
?无法更新域类,我在问题中提到了这一点。但即使这是可行的,它唯一的影响就是将单调的“复制属性”代码从派生类移动到基类。它还得写。。你知道那是无效的,对吗?构造函数没有被继承。@qes:Lol,忘记了继承对象中的声明。。将修复它。那么您应该如何具体实例化一个用现有的
MyDomainModel
填充的
MyViewModel
?无法更新域类,我在问题中提到了这一点。但即使这是可行的,它唯一的影响就是将单调的“复制属性”代码从派生类移动到基类。它还得写。。你知道那是无效的,对吗?构造函数没有被继承。@qes:Lol,忘记了继承对象中的声明。。你的目标是什么?您只是想扩展类的功能?或者你真的想创建其他具有不同功能的实例吗?你的目标是什么?您只是想扩展类的功能?或者你真的想创建其他具有不同功能的实例吗?我想不是。首先,信息是按视图模型定制的。其次,视图模型是重用的,最好将这种简单的逻辑保留在视图模型中,而不是分散在控制器中。对于从域模型到视图的复杂转换,模型由自定义代码处理,这很好。信息技术