C# 基类(域模型)到派生类(视图模型)的转换
我在MVC应用程序中看到以下模式,其中基本上派生类向域类添加了次要功能,很多时候只是显示依赖于基类中其他属性的只读属性。不必编写非常基本的属性复制代码(C# 基类(域模型)到派生类(视图模型)的转换,c#,asp.net-mvc-3,C#,Asp.net Mvc 3,我在MVC应用程序中看到以下模式,其中基本上派生类向域类添加了次要功能,很多时候只是显示依赖于基类中其他属性的只读属性。不必编写非常基本的属性复制代码(between//*****/*****)的更好方法是什么 编辑:我想通过这个问题来解决在应用程序中传播太多“属性复制”代码的问题。不幸的是,错误的示例选择(源自DomainModel的ViewModel)导致了另一个领域的讨论。在基础中创建一个副本构造函数 这将在派生类中为您节省大量代码 public class MyDomainModel {
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,忘记了继承对象中的声明。。你的目标是什么?您只是想扩展类的功能?或者你真的想创建其他具有不同功能的实例吗?你的目标是什么?您只是想扩展类的功能?或者你真的想创建其他具有不同功能的实例吗?我想不是。首先,信息是按视图模型定制的。其次,视图模型是重用的,最好将这种简单的逻辑保留在视图模型中,而不是分散在控制器中。对于从域模型到视图的复杂转换,模型由自定义代码处理,这很好。信息技术