ASP.NET Core 3.0 中的 ExpressionHelper 的替代品?
Replacement for ExpressionHelper in ASP.NET Core 3.0?
在 ASP.NET Core 2.x 中,我使用 ExpressionHelper
class 的静态方法 GetExpressionText
用于 IHtmlHelper<T>
扩展方法:
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class HtmlHelperExtensions
{
public static string GetExpressionText<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression)
{
return ExpressionHelper.GetExpressionText(expression);
}
}
在 ASP.NET Core 3.0 命名空间 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
中不再可用。因此编译器抛出异常:
The name 'ExpressionHelper' does not exist in the current context.
ExpressionHelper
功能的正确替代品是什么?
ModelExpressionProvider
来自 Microsoft.AspNetCore.Mvc.ViewFeatures
可以使用。
方法 GetExpressionText
包装了 ExpressionHelper
的相同方法,并添加了额外的缓存或结果,如本 Github issue 中所述。
using Microsoft.AspNetCore.Mvc.ViewFeatures;
public static class HtmlHelperExtensions
{
public static string GetExpressionText<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression)
{
var expressionProvider = htmlHelper.ViewContext.HttpContext.RequestServices
.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
return expressionProvider.GetExpressionText(expression);
}
}
不依赖于 IHtmlHelper 且可用于其他场景的替代解决方案如下:
public static class StringExtensions
{
private static readonly ModelExpressionProvider ModelExpressionProvider = new ModelExpressionProvider(new EmptyModelMetadataProvider());
public static string GetExpressionText<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> expression)
{
return ModelExpressionProvider.GetExpressionText(expression);
}
}
需要记住的一点是,ModelExpressionProvider 内部包含一个 ConcurrentDictionary 用于缓存,这就是为什么将其设为静态可能有益的原因。
正如 Nenad 所说,ModelExpressionProvider.GetExpressionText 只是 ExpressionHelper.GetExpressionText 的包装器,添加了缓存参数:
public class ModelExpressionProvider : IModelExpressionProvider
{
private readonly IModelMetadataProvider _modelMetadataProvider;
private readonly ConcurrentDictionary<LambdaExpression, string> _expressionTextCache;
....
public string GetExpressionText<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
{
if (expression == null)
{
throw new ArgumentNullException(nameof(expression));
}
return ExpressionHelper.GetExpressionText(expression, _expressionTextCache);
}
....
}
在 ASP.NET Core 2.x 中,我使用 ExpressionHelper
class 的静态方法 GetExpressionText
用于 IHtmlHelper<T>
扩展方法:
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
public static class HtmlHelperExtensions
{
public static string GetExpressionText<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression)
{
return ExpressionHelper.GetExpressionText(expression);
}
}
在 ASP.NET Core 3.0 命名空间 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
中不再可用。因此编译器抛出异常:
The name 'ExpressionHelper' does not exist in the current context.
ExpressionHelper
功能的正确替代品是什么?
ModelExpressionProvider
来自 Microsoft.AspNetCore.Mvc.ViewFeatures
可以使用。
方法 GetExpressionText
包装了 ExpressionHelper
的相同方法,并添加了额外的缓存或结果,如本 Github issue 中所述。
using Microsoft.AspNetCore.Mvc.ViewFeatures;
public static class HtmlHelperExtensions
{
public static string GetExpressionText<TModel, TResult>(
this IHtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TResult>> expression)
{
var expressionProvider = htmlHelper.ViewContext.HttpContext.RequestServices
.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
return expressionProvider.GetExpressionText(expression);
}
}
不依赖于 IHtmlHelper 且可用于其他场景的替代解决方案如下:
public static class StringExtensions
{
private static readonly ModelExpressionProvider ModelExpressionProvider = new ModelExpressionProvider(new EmptyModelMetadataProvider());
public static string GetExpressionText<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> expression)
{
return ModelExpressionProvider.GetExpressionText(expression);
}
}
需要记住的一点是,ModelExpressionProvider 内部包含一个 ConcurrentDictionary 用于缓存,这就是为什么将其设为静态可能有益的原因。
正如 Nenad 所说,ModelExpressionProvider.GetExpressionText 只是 ExpressionHelper.GetExpressionText 的包装器,添加了缓存参数:
public class ModelExpressionProvider : IModelExpressionProvider
{
private readonly IModelMetadataProvider _modelMetadataProvider;
private readonly ConcurrentDictionary<LambdaExpression, string> _expressionTextCache;
....
public string GetExpressionText<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
{
if (expression == null)
{
throw new ArgumentNullException(nameof(expression));
}
return ExpressionHelper.GetExpressionText(expression, _expressionTextCache);
}
....
}