在ASP.NET Core 3.0中替代ExpressionHelper?

Nen*_*nad 4 c# asp.net-core-3.0

在ASP.NET核心2.X我是用静态方法GetExpressionTextExpressionHelperIHtmlHelper<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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在ASP.NET Core 3.0中,命名空间Microsoft.AspNetCore.Mvc.ViewFeatures.Internal不再可用。因此,编译器将引发异常:

名称“ ExpressionHelper”在当前上下文中不存在。

什么是ExpressionHelper功能的适当替代品?

Nen*_*nad 5

ModelExpressionProviderMicrosoft.AspNetCore.Mvc.ViewFeatures可以使用。

方法GetExpressionText包装相同的方法,ExpressionHelper并如此Github问题中所述添加其他缓存或结果。

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 expresionProvider = htmlHelper.ViewContext.HttpContext.RequestServices
            .GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;

        return expresionProvider.GetExpressionText(expression);
    }
}
Run Code Online (Sandbox Code Playgroud)


Aug*_*eto 5

不依赖 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

需要记住的是,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);
    }
    ....
}
Run Code Online (Sandbox Code Playgroud)