我正在尝试在强类型视图上创建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调用,如上所述(“不包含定义for and no extension method blah blah blah“)。当然,明确的演员阵容会使这项工作成功,但这正是我想要避免的。
答案 0 :(得分:0)
如果您可以将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);
}
这应该隐含地解决。