[英]How do you implement this generic class?
I have a frontend ASP.NET MVC website, which contacts a backend service. 我有一个前端ASP.NET MVC网站,该网站与后端服务联系。 The frontend and backend use DTO's to communicate.
前端和后端使用DTO进行通信。
public class MyDto
{
public string Name {get;set;}
}
I don't want to show this DTO directly to users of my website, so I made a viewmodel that takes the same data. 我不想直接向我的网站用户显示此DTO,所以我制作了一个使用相同数据的ViewModel。
public class MyViewModel
{
public string Name {get;set;}
}
Now, for all these viewmodels, the update, post and other methods are all the same. 现在,对于所有这些视图模型,update,post和其他方法都相同。 Instead of retyping the same controller actions for every viewmodel, I decided to create an abstract controller that contains all these methods.
我决定不为每个视图模型重新键入相同的控制器操作,而是决定创建一个包含所有这些方法的抽象控制器。 So I made an interface so all my view models would have the same behaviour:
因此,我创建了一个接口,以便所有视图模型都具有相同的行为:
public interface IViewModelControllerActions<T>
{
IUpdateData<T> UpdateData { get; } //IUpdateData defined somewhere else
IUploadData<T> UploadData { get; } // IUploadData defined somewhere else
// definitions for other actions
}
Which I added to my 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 */ } }
}
And create the abstract controller: 并创建抽象控制器:
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
}
The idea is: when a new dto and viewmodel are introduced, all I have to do is implement the IViewModelControllerActions interface on my viewmodel: 这个想法是:引入新的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 */ } }
}
And create a new empty controller that inherits from the abstract one: 并创建一个继承自抽象控制器的新空控制器:
public class MyNewCoolerController : ViewModelController<MyNewCoolerViewModel> {}
So that all logic inside the controller will be already implemented. 这样控制器内部的所有逻辑都将已经实现。 However, I get this error message:
但是,我收到此错误消息:
The type MyNewCoolerViewModel cannot be used as type parameter T in the generic type or method ViewModelController<T>.
MyNewCoolerViewModel类型不能用作泛型类型或方法ViewModelController <T>中的类型参数T。 There is no implicit reference conversion from MyNewCoolerViewModel to IViewModelControllerActions<MyNewCoolerViewModel>
从MyNewCoolerViewModel到IViewModelControllerActions <MyNewCoolerViewModel>没有隐式引用转换
I understand the error message, however, I don't understand how to fix it. 我了解错误消息,但是,我不知道如何解决它。 How do I get this setup to work?
如何使该设置起作用?
Have you looked at/considered Automapper ? 您是否看过/考虑过Automapper ?
I think you're overcomplicating it - I realize it's not a direct answer to your question, but the problem of DTO -> ViewModel is typically solved using a mapper of some kind. 我认为您过于复杂了-我意识到这不是您问题的直接答案,但DTO-> ViewModel的问题通常是使用某种映射器解决的。 What would be wrong with that approach in your project?
您的项目中的这种方法有什么问题?
This feels kind of like a puzzle, but after looking at it for a while, the main issue is that T in the controller is self referential: 这听起来像是一个难题,但是看了一会儿之后,主要的问题是控制器中的T是自引用的:
abstract class ViewModelController<T>: Controller where T : IViewModelControllerActions<T>
Which in this case means that T has to be of type IViewModelControllerActions<IViewModelControllerActions<T>>
. 在这种情况下,这意味着T必须为
IViewModelControllerActions<IViewModelControllerActions<T>>
。 The controller should be either ViewModelController<T,U>:Controller where T:IViewModelController<U>
or ViewModelController<IViewModelControllerAction<T>>
depending on how you intend to use it 控制器应为
ViewModelController<T,U>:Controller where T:IViewModelController<U>
或ViewModelController<IViewModelControllerAction<T>>
具体取决于您打算如何使用它
But to be honest, this doesn't (imo) align very well with the MVC-architecture. 但老实说,这(imo)与MVC架构不太吻合。 As for controller and reuse, I think you could skip the entire IViewModelControllerAction-interface and just override the methods on a base class, something like this:
至于控制器和重用,我认为您可以跳过整个IViewModelControllerAction-interface并只重写基类上的方法,如下所示:
public abstract class ViewModelController<T,U>:Controller{ public ActionResult Update(T item){...} public abstract void Save(U dto); }
The U might be optional depending on how you intend to implement things, but it's a start. 根据您打算如何实现,U可能是可选的,但这只是一个开始。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.