HtmlHelper关于通用视图模型的类型参数
本文关键字:类型参数 模型 视图 于通用 HtmlHelper | 更新日期: 2023-09-27 18:04:13
我试图在强类型视图上创建一个HtmlHelper方法,其中视图模型是通用的。但是有一个复杂的问题。我想简化语法,以便可以在视图模型上指定属性的成员表达式。
public interface ViewModel<T>
{
T Model { get; set; }
}
public class DocViewModel : ViewModel<Document>
{
public IEnumerable<string> Options { get; set; }
public Document Model { get; set; }
}
public class Document
{
public string Name { get; set; }
public string Value { get; set; }
}
现在,我可以很容易地创建一个引用视图模型本身的帮助器,并像这样使用它:
@model DocViewModel
<div>
@Html.DoSomething(vm => vm.Options);
@Html.DoSomethingElse(vm => vm.Model.Name);
@Html.DoSomethingYetAgain(vm => vm.Model.Value);
</div>
但是我希望能够在模型上简单地传递一个表达式,像这样:
@model DocViewModel
<div>
@Html.DoSomething(vm => vm.Options);
@Html.DoSomethingElse(vm => vm.Name);
@Html.DoSomethingYetAgain(vm => vm.Value);
</div>
现在,我可以用这样一种方式编写帮助器,如果我在调用中显式引用类型参数,我就可以这样做:
@model DocViewModel
<div>
@Html.DoSomething<Document>(vm => vm.Name);
</div>
但是那有点违背了我所追求的目的。似乎我应该能够编写一个HtmlHelper,可以利用视图是强类型的DocViewModel,它本身就是一个ViewModel,并且@Html()返回
HtmlHelper<DocViewModel> //HtmlHelper<ViewModel<Document>>
使Document所表示的类型参数隐式已知,这样我就可以写
public static string DoSomethingElse<TModel, TProperty>(this HtmlHelper<ViewModel<TModel>> helper, Expression<Func<TModel, TProperty>> expression)
{
return "Whatever";
}
,但这种转换不能完成。有什么办法可以帮我吗?还是我只能忍受这些丑陋的语法?
编辑:将不正确的引用"KoViewModel"改为"ViewModel"
再次编辑:此外,使ViewModel泛型的要点是,我可以声明任何其他类型的ViewModel:
public class ProgramViewModel : ViewModel<Program>
{
//other stuff
public Program Model { get; set; }
}
public class Program
{
public string Something { get; set; }
//other properties I want to reference
}
和另一个视图:
@model ProgramViewModel
<div>
@Html.DoSomethingElse(vm => vm.Something)
</div>
再次强调,我希望能够在视图的视图模型和视图模型的Model属性上解引用属性,而不必在方法调用中显式引用类型。
我上面定义的方法的问题是,在HtmlHelper和HtmlHelper之间显然没有隐式转换,因此编译器不能像上面那样解决视图中的@Html调用("不包含定义和没有扩展方法blah blah")。当然,所有的显式强制转换都可以使其工作,但这正是我试图避免的。
如果您可以将ViewModel更改为抽象类,请执行以下操作:
public abstract class ViewModel<TModel>
{
public class HtmlHelper : HtmlHelper<ViewModel<TModel>> {}
public TModel Model;
}
然后编写如下静态扩展方法:
public static TProperty DoSomethingElse<TModel, TProperty>(this ViewModel<TModel>.HtmlHelper helper, Expression<Func<TModel, TProperty>> expression)
{
return default(TProperty);
}