2017-02-14 34 views
2

我想用反射來自動生成一個視圖。 Html.DisplayFor和一些其他助手採取Expression<Func<,>>LambdaExpression派生。好像我可以手動生成自己的λ,然後把它傳遞,但它拋出這個錯誤:我可以爲MVC的HTML幫助程序使用LambdaExpression類型嗎?

The type arguments for method 'DisplayExtensions.DisplayFor<TModel, TValue>(HtmlHelper<TModel>, Expression<Func<TModel, TValue>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.`

這裏是我的標記:

<tr> 
    @foreach (var pi in Model.GetType().GetProperties()) 
    { 
     <td> 
      @Html.DisplayFor(ExpressionHelpers.GetPropertyGetterLambda(pi)) 
     </td> 
    } 
</tr> 

我敢肯定發生了什麼事是.DisplayFor需要泛型類型參數來推斷Func<TModel, TValue>的類型,但我使用的是隱藏類型的LambdaExpression

這似乎是唯一的方法來做我想要的是建立/編譯一個表達式,實際上使用類型安全參數調用.DisplayFor,但似乎過於複雜。

是否有另一種方式來實現我的目標,或者我會更好的直接輸出結果到HTML而不是調用幫助者?

編輯:每請求,這裏的代碼GetPropertyGetterLambda

public static LambdaExpression GetPropertyGetterLambda(PropertyInfo pi, BindingTypeSafety TypeSafety) 
{ 
    if (pi.CanRead) 
    { 
     ParameterExpression entityParameter = Expression.Parameter(TypeSafety.HasFlag(BindingTypeSafety.TypeSafeEntity) ? 
      pi.ReflectedType : typeof(object)); 
     LambdaExpression lambda = Expression.Lambda(GetPropertyReadExpression(entityParameter, pi, TypeSafety), entityParameter); 
     return lambda; 
    } 
    else 
    { 
     return null; 
    } 
} 
+0

你能顯示那個方法的實現嗎? –

+0

@EhsanSajjad更新 – oscilatingcretin

回答

0

沒有針對此,我建議首先另一種解決方案。改變你的for循環的DisplayForModel電話:

@Html.DisplayForModel() 

這將呈現出所有屬性,使用DisplayFor內部。您可以通過修改DisplayTemplates文件夾中的Object.cshtml(在您正在使用的Views文件夾中或在Shared文件夾中進行全局應用)來修改此內容。

如果這還不夠,或者你確實想用LambdaExpression,這裏有一個選擇。它將要求您添加一個DisplayFor<TModel>(LambdaExpression expression)擴展方法。這將是類似的東西(請注意,我沒有真正測試過這個,但是這很接近需要的):

public static IHtmlString DisplayFor<TModel>(this HtmlHelper<TModel> helper, LambdaExpression expression) 
    { 
     var wrapperClass = typeof(DisplayExtensions); 
     ///find matching DisplayFor<TModel, TProperty> method 
     var matchingMethod = wrapperClass.GetMethods() 
      .Single(c => c.IsStatic 
       && c.Name == "DisplayFor" 
       && c.GetGenericArguments().Count() == 2 
       && c.GetParameters().Count() == 2 //overloads don't have same # of parameters. This should be sufficient. 
       ).MakeGenericMethod(typeof(TModel), expression.ReturnType); //Make generic type from the TModel and the Return Type 

     //invoke the method. The result is a IHtmlString already, so just cast. 
     return (IHtmlString) matchingMethod.Invoke(null, new Object[] { helper, expression }); 
    } 
+0

您的第二個解決方案基本上是我將要回溯的,但使用反射在運行時使用表達式樹生成委託。我不認爲他首先會在我的情況下工作,但很高興知道這件事。 – oscilatingcretin

+0

@oscilatingcretin你爲什麼認爲第一個不行? –

相關問題