将IHtmlHelper与依赖项注入结合使用

时间:2019-03-08 16:34:15

标签: asp.net-core razor

我将创建一个控制器,该控制器响应通过IHtmlHelper接口创建的第三方IHtmlContent,而不使用View()方法。实际上,我正在使用一种解决方法:

我创建了IHtmlHelper的扩展功能,其行为类似于“主”,而其他静态函数的行为类似于“从属”。主站函数基于它作为参数接收的数据结构来调用从站。从站基于第三方库创建IHtmlContent。完成所有从站功能后,控制器将发送回响应。 此行为在控制器调用的cshtml视图内部。

是否可以使用依赖注入将IHtmlHelper作为控制器构造函数参数?

类似

public class MyTestController 
{
    private readonly IHtmlHelper _html;

    public MyTestController(IHtmlHelper html) {
     _html = html;
    }
}

如果可能的话,我会简化许多操作,因为我正在使用此Master / Slave函数来复制类的行为

在这里您可以找到有关我的代码现在如何工作以及如何更改代码的纯示例 https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs

我需要此组件,因为第三方库是IHtmlHelper的扩展

2 个答案:

答案 0 :(得分:1)

简短答案:是。


如果查看the source code of MVC,您会发现IHtmlHelper已注册为临时服务:

    internal static void AddViewServices(IServiceCollection services)
    {

        ...

        //
        // HTML Helper
        //
        services.TryAddTransient<IHtmlHelper, HtmlHelper>();
        services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
        services.TryAddSingleton<IHtmlGenerator, DefaultHtmlGenerator>();
        services.TryAddSingleton<ModelExpressionProvider>();
        // ModelExpressionProvider caches results. Ensure that it's re-used when the requested type is IModelExpressionProvider.
        services.TryAddSingleton<IModelExpressionProvider>(s => s.GetRequiredService<ModelExpressionProvider>());
        services.TryAddSingleton<ValidationHtmlAttributeProvider, DefaultValidationHtmlAttributeProvider>();

        services.TryAddSingleton<IJsonHelper, DefaultJsonHelper>();

        ...

    }

换句话说,您可以根据需要注入IHtmlHelper服务。

提醒一下,我们应该始终更喜欢在View Layer中使用IHtmlHelper

答案 1 :(得分:1)

我感谢Itminus回答我。

但是仅在控制器构造函数上调用IHtmlHelper还是不够的,您必须在使用IHtmlHelper之前将其上下文化。

我想分享我找到的另一个解决方案并解决我的问题,也许对其他用户可能有用。 请参阅https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs来记住我的目标。

  1. 要解决我的问题,我创建了一个名为HtmlHelperAdapter的类,其中包含我需要的一些实例。
public class MyHtmlHelperAdapter
{
        public IHtmlHelper _html;

        public NubessHtmlHelperAdapter(IHtmlHelper html)
        {
            _html = html;
        }

        public IHtmlHelper Html => _html;
        public ViewContext ViewContext => _html.ViewContext;
        public HttpContext HttpContext => _html.ViewContext.HttpContext;
        public ViewDataDictionary ViewData => _html.ViewData;
        public IServiceProvider provider => _html.ViewContext.HttpContext.RequestServices;
}
  1. 之后,我为IHtmlHelper创建了扩展方法
public static class MyBuilderExtension
{
        public static MyBuilder Nubess(this IHtmlHelper html)
        {
            return new MyBuilder(new MyHtmlHelperAdapter(html));
        }
}

MyBuilder在哪里

public class MyBuilder
    {
        private readonly MyHtmlHelperAdapter _htmlHelper;

        public MyBuilder(MyHtmlHelperAdapter htmlHelper)
        {
            _htmlHelper = htmlHelper;
        }

        public FormBuilder<object> Form<T>(IDictionary<string, string> customizeArgs = null, FormBuilder<object> externalForm = null)
        {
            return new FormBuilder(_htmlHelper, typeof(T), customizeArgs, externalForm).Build();
        }
    }
  1. 现在,由于 MyHtmlHelperAdapter
  2. ,我可以使用 class 为视图创建自定义内容。
 public class FormBuilder
 {
        private MyHtmlHelperAdapter _htmlHelper;
        private readonly IStringLocalizer<SharedResources> _localizer;
        private readonly LinkGenerator _linkGenerator;
        private readonly IEngine _engine;
        private readonly IEngineElement _element;
        private readonly Type _typeDescriptor;
        private readonly IDictionary<string, string> _descriptorArgs;

        /* variabili per semplificare la gestione del builder */
        private readonly FormBuilder<object> Form;
        private readonly FormConfig Config;
        private readonly IList<FormGroupConfig> Groups;
        private readonly IList<FormItemConfig> Items;
        private readonly IDictionary<string, string> FormOptions;

        private readonly string _clientPrefix = "smtForm_{0}_";

        public FormBuilder(MyHtmlHelperAdapter htmlHelper, Type typeDescriptor, IDictionary<string, string> ModelCustomizeArgs = null, FormBuilder<object> externalForm = null)
        {
            _htmlHelper = htmlHelper;
            _localizer = _htmlHelper.provider.GetRequiredService<IStringLocalizer<SharedResources>>() ?? throw new ArgumentNullException();
            _linkGenerator = _htmlHelper.provider.GetRequiredService<LinkGenerator>() ?? throw new ArgumentNullException();
            _engine = _htmlHelper.provider.GetRequiredService<IEngine>() ?? throw new ArgumentNullException();

            //code..
        }


        public FormBuilder<object> Build()
        {
            //code..
            return Form;
        }

     //methods..
}