是否有将模型转换为视图模型的快捷方式?

时间:2016-05-16 23:10:25

标签: c# asp.net .net asp.net-mvc asp.net-mvc-5

我是c#和.NET的新手。我正在学习ASP.NET MVC 5.我发现自己花了额外的时间将模型转换为视图模型。

这是我的模特

public class Overview
{

    public string chain_name { get; set; }
    public int store_id { get; set; }
    public int total_attempts { get; set; }
    public int total_unique_number_called { get; set;  }
    public int total_callable { get; set; }
    public int total_completed_interviews { get; set; }

}

这是我的视图模型

public class OverviewViewModel
{

    public string chain_name { get; set; }
    public int store_id { get; set; }
    public int total_attempts { get; set; }
    public int total_unique_number_called { get; set; }
    public int total_callable { get; set; }
    public int total_completed_interviews { get; set; }
    public decimal? unique_number_per_complete { get; set; }

    public OverviewViewModel()
    {
        unique_number_per_complete = 0;
    }

}

你可以看到Model和ViewModel是相同的,除了over变量,这是一个计算。

要填充我的视图模型,请执行以下操作

var records = conn.Database.SqlQuery<Overview>(query).ToList();

var overView = new List<OverviewViewModel>();

foreach(var record in records){

    var newRecord = new OverviewViewModel();

    newRecord.store_id = record.store_id;

    newRecord.chain_name = record.chain_name;

    newRecord.total_attempts = record.total_attempts;

    newRecord.total_callable = record.total_callable;

    newRecord.total_completed_interviews = record.total_completed_interviews;

    if (record.total_completed_interviews > 0) {
        newRecord.total_unique_number_called = record.total_unique_number_called / record.total_completed_interviews;
    }

    overView.Add(newRecord);
}

我用我的方法看到的两个问题是

  1. 我必须做很多额外的编码,特别是视图模型很大或者我有多个需要计算的变量。
  2. 我觉得我正在循环一次额外的时间将我的模型转换为查看模式。
  3. 在c#中有更简单的方法吗?

    对于大型应用程序,此程序是否有更好的方法?我的目标是学习更好地利用我的代码时间。

3 个答案:

答案 0 :(得分:4)

我同意您应该查看automapper,但另一种方法是在OverviewViewModel模型上创建一个构造函数,该构造函数采用Overview对象并填充所有属性。像

这样的东西
public class OverviewViewModel {

    public string chain_name { get; set; }
    public int store_id { get; set; }
    public int total_attempts { get; set; }
    public int total_unique_number_called { get; set; }
    public int total_callable { get; set; }
    public int total_completed_interviews { get; set; }
    public decimal? unique_number_per_complete { get; set; }

    public OverviewViewModel()
    {
        unique_number_per_complete = 0;
    }
public OverviewViewModel(Overview record)
    {
        store_id = record.store_id;

    chain_name = record.chain_name;

    total_attempts = record.total_attempts;

    total_callable = record.total_callable;
    //etc
    }
}  

然后你的代码看起来像

var overView = new List<OverviewViewModel>();

foreach(var record in records){
    overView.Add(new OverViewViewModel(record));
}

答案 1 :(得分:3)

是的,您应该使用Automapper,安装包视图Nuget。 Automapper也是非常可配置的。

http://automapper.org/

首先,创建此类:

public static class AutoMapperConfig
{
    public static void RegisterMappings()
    {
        //Example here, creates "two way" for Overview & OverviewViewModel mapping
        Mapper.CreateMap<Overview, OverviewViewModel>(); //<source, destination>
        Mapper.CreateMap<OverviewViewModel, Overview>(); //<source, destination>
        //..more mapping for other Models and ViewModels.
    }
}

在Global.asax.ApplicationStart()中添加以下行:

AutoMapperConfig.RegisterMappings()

现在你评论中的foreach示例很简单:

foreach (var record in records)
{
    var newRecordOverviewViewModel = Mapper.Map<OverviewViewModel>(record); //<destination>(source)
    overView.Add(newRecordOverviewViewModel);
}

答案 2 :(得分:0)

另一种方法是使用Linq和扩展方法,如下所示

using System.Collections.Generic;
using System.Linq;
using App.Data.Entities;
using App.Business.Models;

namespace App.Business
{
    public static partial class OverviewAdapter
    {
        public static OverviewViewModel ToOverviewViewModel(this Overview overview)
        {
            return new OverviewViewModel
            {
                chain_name                  =   overview.chain_name,
                store_id                    =   overview.store_id,
                total_attempts              =   overview.total_attempts,
                total_unique_number_called  =   overview.total_unique_number_called,
                total_callable              =   overview.total_callable,
                total_completed_interviews  =   overview.total_completed_interviews,
                unique_number_per_complete  =   0
            };
        }

        public static IEnumerable<OverviewViewModel> ToOverviewModelList(this IEnumerable<OverviewViewModel> overviewList)
        {
            return (overviewList != null) ? overviewList.Select(a => a.ToOverviewViewModel()) : new List<OverviewViewModel>();
        }

        // Reverse - ToOverview / ToOverviewList if needed...
   }
}

现在,只要您的Business类在范围内,您就可以在类上使用 可发现的 方法,并且可以内联添加类列表。

var records = conn.Database.SqlQuery<Overview>(query).ToOverviewModelList().ToList();

这种功能更强大的方法直观,简化,如果尚未编写适配器,您可以立即获得反馈。

是否从列表版本返回IEnumerable或List是个人偏好。更广泛的IEnumerable是更传统的解决方案,但我倾向于从List&lt;&gt;列出&lt;&gt;所有的时间并且落入IEnumerable似乎是多余的。