3

私の目標は、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>

ご覧のとおり、さまざまなパーツ間の相互依存性を備えた多層メニューをすばやく構築できます。

ラムダ式を使用してフォームに対してこれと同じ効果を実現したいと思います。

理想的な構文は次のようになります。

<%: Html
    .form()
        .hidden(m=>m.property1)
        .hidden(m=>m.property2)
    .end() %>

問題が発生しているのは、隠しメソッドです。メソッドhiddenに渡さずにコンパイラに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;
    }
}

コメントを使用して上記のコードにエラーを入れました。

ありがとう!

4

3 に答える 3

3

使用しているジェネリック パラメーターが多すぎます。

最初のパラメーターに関連しない2 番目GetFieldValue<TModel, ...>のパラメーターを作成するようなメソッド。 TModel

言い換えれば、それらはあなたが書くことを可能にします

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

これは明らかに間違っています。

代わりに、各メソッドからそのパラメーターを取り除き、代わりにクラスのTModelパラメーターを使用できるようにします。

于 2013-02-22T17:08:33.763 に答える
1

コンパイル エラー「ERRORS: TModel is TModel」は、hidden() のジェネリック宣言で TModel を 2 回宣言したことが原因だと思います。

私はこれをコンパイルしていませんが、次のようなものを試してみます:

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()
    {
    }
}
于 2013-02-22T20:10:38.933 に答える
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()
%>
于 2013-02-22T22:57:51.073 に答える