0

通常,当我创建 MVC 视图时,我首先将我的视图绑定到一个,ExpandoObject这样我就可以快速找出我的视图模型的形状,而不必花时间在强类型视图模型中添加/修改/删除真实属性。

但是一旦我对我的视图模型应该是什么样子有了很好的感觉,我更愿意为它创建一个实际的类。如果我可以从 ExpandoObject 自动生成视图模型,那就太好了。那可能吗?

public virtual ActionResult DoStuff(int stuffId)
{
    // eventually this stuff gets moved to a service class
    dynamic vm = new ExpandoObject();
    using (var ctx = new MyContext())
    {
        vm.Stuff = ctx.Stuff
            .Where(x => x.Id == stuffId)
            .Select(x => new
            {
                Foo = x.Foo,
                Bar = x.Bar
            }).SingleOrDefault().ToExpando();
    }

    // once I know what vm looks like, I'll want to do this to easily create a new class
    // string stronglyType = GenerateStronglyTypeClass(vm);

    return View(vm); 
}

public string GenerateStronglyTypedClass(ExpandoObject object)
{
    // what goes here??
}
4

2 回答 2

2

我首先将我的视图绑定到一个 ExpandoObject,这样我就可以快速找出我的视图模型的形状,而不必花时间在强类型视图模型中添加/修改/删除真实属性。

好吧,你的所作所为很糟糕。很抱歉这么说,但你正在失去强大的打字能力。我不敢相信人们在他们项目Ctrl+AModels文件夹中实际上发现它很难使用,键入一些以结尾的名称ViewModel,然后键入几个prop+Tab+Tab并定义一个真正的强类型视图模型。

相反,人们尝试使用一些扩展、动态、ViewDatas、ViewBags、CrapBags,......

所以这就是我的建议:使用真实的视图模型,忘记那些一周的打字,否则你将继续为 ASP.NET MVC 苦苦挣扎。相信我。就是这样:-)

当你使用AutoMapper自动绑定你的域模型和视图模型时,你将有更多的时间喝啤酒,就像我一样:

public ActionResult DoStuff(int stuffId)
{
    using (var ctx = new MyContext())
    {
        var model = ctx.Stuff.Where(x => x.Id == stuffId);
        var vm = Mapper.Map<IEnumerable<MyDomainModel>, IEnumerable<MyViewModel>>(model);
        return View(vm);
    }
}

看看这有多有趣?

显然,如果您想有机会对控制器操作进行单元测试,则应该使用存储库而不是硬编码 dome Linq-To-I-Don't-Know-What 控制器中的上下文,如下所示:

public ActionResult DoStuff(int stuffId)
{
    var model = _stuffRepository.GetStuffs(stuffId);
    var vm = Mapper.Map<IEnumerable<MyDomainModel>, IEnumerable<MyViewModel>>(model);
    return View(vm);
}

有这么难吗?

您甚至可以编写自定义操作自动映射器属性,您的操作甚至可能如下所示:

[AutoMap(typeof(IEnumerable<MyDomainModel>), typeof(IEnumerable<MyViewModel>))]
public ActionResult DoStuff(int stuffId)
{
    var model = _stuffRepository.GetStuffs(stuffId);
    return View(model);
}

好的,我们正在变得更短、更薄、更轻。控制器操作应该是怎样的。节食

于 2011-07-11T18:32:40.030 回答
1

在运行时生成的任何类型的类(比如发出)都不会带来太大的好处,因为如果你不知道编译类型的类型,你仍然会调用 dynamic 并且 expando 实际上会击败我的 poco 类测试。如果您的生成类要创建可以工作的 ac# 文件,但您必须包含该文件并替换代码,重新编译,嗯,但可以工作。

开源框架具有ImpromptuInterface具有构建器语法,允许您以相同的方式分配属性或创建对象图,无论类型是什么(expando 或 poco),只需更改几个类型。

 dynamic New = Builder.New<ExpandoObject>();

  var person = New.Person(
      FirstName: "George",
      LastName: "Washington"
  );

然后在你的开发过程中你可以定义你的静态类型

  public class Person{
      public string FirstName{get;set;}
      public string LastName{get;set;}
  }


  dynamic New = Builder.New<Person>();

  Person person = New.Person(   //we are static typing after this point
      FirstName: "George",
      LastName: "Washington"
  );

它还具有其他一些功能,例如在运行时包装静态接口也可能对您有用。

于 2011-07-18T14:18:07.743 回答