在MVC.Net中链接lambda表达式,而不重复传递HtmlHelper对象

本文关键字:对象 HtmlHelper Net MVC 链接 表达式 lambda | 更新日期: 2023-09-27 18:00:51

我的目标是创建一个对象,允许在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;
    }
}

我用注释把错误放在上面的代码中。

谢谢!

在MVC.Net中链接lambda表达式,而不重复传递HtmlHelper对象

您使用了太多的泛型参数。

GetFieldValue<TModel, ...>这样的方法创建一个第二个TModel参数,该参数与第一个参数无关。

换句话说,它们允许您编写

new RouteForm<PersonModel>().GetFieldValue<TruckModel, ...>()

这显然是错误的。

相反,只需从每个方法中去掉该参数,让它们使用类的TModel参数。

我猜编译错误"ERRORS:TModel is 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()
    {
    }
}

多亏了你们两个,我能够创建一个实现我想要的语法的类。

(这篇文章简化了课程(类别:

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()
%>