我的目标是创建一个对象,以允许在MVC.Net视图中链接命令。
以下是使用此概念创建的菜单视图中的示例:
<nav class="navigation">
<%: Html
.menu()
.item("Introduction", "Introduction", "Home")
.item("About", "About", "Home")
.item("Systems", "Index", "Systems")
/*.item("Categories", "Categories", "Health")*/
.item("Test Cases", "TestCases", "Testing")
.category("Logging")
.item("UniMon Events", "UniMonEvents", "Logging")
.end()
.end() %>
</nav>
正如您所看到的,它允许快速构建多层菜单,各个部分之间具有相互依赖性。
我想对使用lambda表达式的表单实现同样的效果。
理想的语法如下:
<%: Html
.form()
.hidden(m=>m.property1)
.hidden(m=>m.property2)
.end() %>
我遇到麻烦的地方是隐藏方法。似乎没有办法让编译器推断 m 而不将其传递给方法隐藏。
我可以实现这种语法:
<%: Html
.form()
.hidden(Html, m=>m.property1)
.hidden(Html, m=>m.property2)
.end() %>
使用此类和扩展方法(未显示):
public class RouteForm
{
public HtmlHelper HtmlHelper { get; private set; }
public Dictionary<string, string> PostData { get; private set; }
public RouteForm(HtmlHelper htmlHelper)
{
HtmlHelper = htmlHelper;
PostData = new Dictionary<string, string>();
}
public RouteForm hidden<TModel, TValue>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
{
string name = ExpressionHelper.GetExpressionText(expression);
string value = GetFieldValue(htmlHelper, expression);
PostData.Add(name, value);
return this;
}
private static string GetFieldValue<TModel, TValue>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression)
{
object oValue = expression.Compile()(htmlHelper.ViewData.Model);
string value = (oValue is Enum) ? ((int)oValue).ToString() : oValue.ToString();
return value; ;
}
public MvcHtmlString end()
{
//TODO: render form with post data
return MvcHtmlString.Empty;
}
}
我认为也许一个具有泛型类的类可能就是我想要的,所以我尝试了这个:
public class RouteForm<TModel>
{
public HtmlHelper<TModel> HtmlHelper { get; private set; }
public Dictionary<string, string> PostData { get; private set; }
public RouteForm(HtmlHelper<TModel> htmlHelper)
{
HtmlHelper = htmlHelper;
PostData = new Dictionary<string, string>();
}
public RouteForm<TModel> hidden<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
{
string name = ExpressionHelper.GetExpressionText(expression);
string value = GetFieldValue(expression);
PostData.Add(name, value);
return this;//ERRORS: TModel is TModel
}
private string GetFieldValue<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
{
object oValue = expression.Compile()(
(TModel)HtmlHelper.ViewData.Model //ERRORS: Cannot convert type TModel to TModel
);
string value = (oValue is Enum) ? ((int)oValue).ToString() : oValue.ToString();
return value; ;
}
public MvcHtmlString end()
{
//TODO: render form with post data
return MvcHtmlString.Empty;
}
}
我使用评论将错误放在上面的代码中。
谢谢!
答案 0 :(得分:3)
您使用的参数太多了。
GetFieldValue<TModel, ...>
之类的方法会创建第二个 TModel
参数,该参数与第一个参数无关。
换句话说,他们允许你写
new RouteForm<PersonModel>().GetFieldValue<TruckModel, ...>()
这显然是错误的。
相反,只需从每个方法中删除该参数,然后让它们使用类TModel
参数。
答案 1 :(得分:1)
我猜编译错误“错误:TModel是TModel”是由于在hidden()的泛型声明中两次声明TModel引起的。
我没有编译过这个,但我会尝试这样的事情:
public static class HtmlHelperExtensions
{
public static RouteForm<TModel> form(this HtmlHelper helper, TModel model)
{
return new RouteForm<TModel>(helper);
}
}
public class RouteForm<TModel>
{
public RouteForm<TModel> hidden(Expression<Func<TModel, TValue>> expression)
{
}
public MvcHtmlString end()
{
}
}
答案 2 :(得分:0)
感谢你们两位,我能够创建一个实现我正在寻找的语法的类。
(此帖子简化了课程) 的类:强>
public class RouteForm<TModel>
{
public HtmlHelper<TModel> HtmlHelper { get; private set; }
public RouteForm(HtmlHelper<TModel> htmlHelper)
{
HtmlHelper = htmlHelper;
}
public RouteForm<TModel> hidden<TValue>(Expression<Func<TModel, TValue>> expression)
{
return this;
}
public MvcHtmlString end()
{
return MvcHtmlString.Empty;
}
}
扩展方法:
public static RouteForm<TModel> form<TModel>(this HtmlHelper<TModel> helper)
{
return new RouteForm<TModel>(helper);
}
标记语法:
<%: Html
.form()
.hidden(m=>m.Property1)
.hidden(m=>m.Property2)
.end()
%>