你如何实现这个泛型类?

时间:2016-03-29 11:39:20

标签: c# asp.net-mvc

我有一个前端ASP.NET MVC网站,它与后端服务联系。前端和后端使用DTO进行通信。

public class MyDto
{
    public string Name {get;set;}
}

我不想直接向我网站的用户展示此DTO,因此我创建了一个采用相同数据的视图模型。

public class MyViewModel
{
    public string Name {get;set;}
}

现在,对于所有这些视图模型,更新,发布和其他方法都是相同的。我没有为每个视图模型重新输入相同的控制器动作,而是决定创建一个包含所有这些方法的抽象控制器。所以我创建了一个界面,所以我的所有视图模型都会有相同的行为:

 public interface IViewModelControllerActions<T>
 { 
    IUpdateData<T> UpdateData { get; } //IUpdateData defined somewhere else
    IUploadData<T> UploadData { get; } // IUploadData defined somewhere else
    // definitions for other actions
 }

我添加到我的viewmodel:

public class MyViewModel : IViewModelControllerActions<MyDto>
{
    public string Name {get;set;}

    public IUpdateData<T> UpdateData { get { /* Do stuff to get UpdateData */ } }
    public IUploadData <T> UploadData { get { /* Do stuff to get UploadData */ } }
}

创建抽象控制器:

 public abstract class ViewModelController<T>: Controller where T : IViewModelControllerActions<T>
 {
      [HttpPost]
      public ActionResult Upload(T input)
      {
           // do stuff with T.UploadData to upload
      }

      [HttpPost]
      public ActionResult Update(T input)
      {
           // do stuff with T.UpdateData to update
      }

      // other methods
 }

这个想法是:当引入新的dto和viewmodel时,我所要做的就是在我的viewmodel上实现IViewModelControllerActions接口:

public class MyNewCoolerViewModel : IViewModelControllerActions<MyNewCoolerDto>
{
    public string Name {get;set;}
    public string AnotherNewName {get;set;}
    public int ANumber {get;set;}

    public IUpdateData<T> UpdateData { get { /* Do stuff to get UpdateData */ } }
    public IUploadData <T> UploadData { get { /* Do stuff to get UploadData */ } }
}

创建一个新的空控制器,它继承自抽象控制器:

public class MyNewCoolerController : ViewModelController<MyNewCoolerViewModel> {}

这样控制器内的所有逻辑都将被实现。但是,我收到此错误消息:

  

MyNewCoolerViewModel类型不能用作类型参数T in   泛型类型或方法ViewModelController&lt; T&gt;。从MyNewCoolerViewModel到IViewModelControllerActions&lt; MyNewCoolerViewModel&gt;

没有隐式引用转换

我理解错误消息,但是,我不明白如何解决它。如何使此设置生效?

2 个答案:

答案 0 :(得分:0)

你看过/考虑过Automapper了吗?

我认为你过度复杂了 - 我意识到这不是你问题的直接答案,而是DTO的问题 - &gt; ViewModel通常使用某种映射器来解决。在您的项目中,这种方法会出现什么问题?

答案 1 :(得分:0)

这感觉有点像拼图,但在看了一会儿之后,主要问题是控制器中的T是自我引用的:

ViewModelController<T,U>:Controller where T:IViewModelController<U>

在这种情况下,这意味着T必须是ViewModelController<IViewModelControllerAction<T>>类型。 控制器应该是public abstract class ViewModelController<T,U>:Controller{ public ActionResult Update(T item){...} public abstract void Save(U dto); }<?php echo $this->getMessagesBlock()->getGroupedHtml(); ?> ,具体取决于您打算如何使用它

但说实话,这并没有(imo)与MVC架构很好地对齐。至于控制器和重用,我认为你可以跳过整个IViewModelControllerAction接口,只是覆盖基类上的方法,如下所示:

SELECT l.Name, l.Model, l.Engine_Type, m.ID, g.Name FROM db.vehicle_part k JOIN db.vehicle l ON k.ID_Vehicle = l.ID JOIN db.part m ON k.ID_Part = m.ID JOIN db.part_generic_part b ON b.ID_Part = m.ID JOIN db.generic_part c ON c.ID = b.ID_Generic_part JOIN db.generic_part_name d ON c.ID = d.ID_Generic_Part JOIN db.part_category_generic_part e ON c.ID = e.ID_generic_part JOIN db.part_category f ON e.ID_category = f.ID JOIN db.part_category_name g ON f.ID = g.ID_Part_Category JOIN db.lang h ON g.ID_Lang = h.ID WHERE l.Name = 'BMW' AND l.Model = '3 (E30)' AND l.Engine_Type= '316 i' AND g.ID_Lang =2

U可能是可选的,具体取决于您打算如何实施,但这只是一个开始。