具有依赖项注入的过滤器属性

时间:2019-01-16 17:09:27

标签: c# .net asp.net-core

我正在尝试完全理解依赖注入。我正在定义一个过滤器,想从配置文件中读取。在过滤器内部实例化配置是一种更好的做法,还是可以在全局(例如在启动过程中)实例化此配置?如果是这样,那么有关如何执行操作的任何指针?

public class CompanyFilter : ActionFilterAttribute
{
   string _ERPUrl;
   public CompanyFilter(IConfiguration iconfiguration)
   {
       ERPUrl = iconfiguration.GetSection("AppSettings").GetSection("ERPUrl").Value;  

    }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.Controller is Controller controller)
            controller.ViewBag.ERPUrl = _ERPUrl;      
            //filterContext.Controller.ViewBag.Company = "Test";
    }
}

启动类

public class Startup
{


    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
....

控制器

namespace Projects.Controllers
{
    [CompanyFilter]
    public class HomeController : Controller
    {
....

产生以下错误。

  

Controllers \ HomeController.cs(14,6):错误CS7036:没有提供与'CompanyFilter.CompanyFilter(IConfiguration)'所需的形式参数'iconfiguration'相对应的参数

3 个答案:

答案 0 :(得分:0)

我建议您使用IOptions<T>从文件中检索配置,而该文件具有.Net Core支持的所有优点。您可以查看操作方法here

另外,要将其注入到可靠的注入解析器中,请在services.AddTransient(p => new MyService(mySettings));函数中添加ConfigureServices()作为瞬态或作用域或单例(确定哪个更适合您)。

如果您坚持使用IConfiguration来检索配置并解决所遇到的问题,则应像这样IConfiguration注入services.AddSingleton(Configuration);实例。希望这能解决您的问题。

答案 1 :(得分:0)

根据此处的一些反馈,通过将其添加到Startup.cs,以下操作是可行的。

services.AddMvc(options => {
   options.Filters.Add(new ERPFilter(Configuration));
}

可以根据以上几点对网址进行分解,以提高性能。

url = ...
services.AddMvc(options => {
   options.Filters.Add(new ERPFilter(url));
}

答案 2 :(得分:0)

要根据其他人和我自己昨天提供的评论提供答案,建议将IOptions<T>注入到您的过滤器或任何其他需要注入配置数据的对象中。

您可以像这样将ERP设置添加到appSettings.json文件中

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Erp": {
    "Url": "https://localhost"
  }
}

要将设置注入依赖项,您必须通过ConfigureServices注册它,您还会注意到CompanyFilter是通过IServiceCollection添加到AddTransient的,这是为了允许ServiceFilterAttribute在以后的阶段进行解析,并注入过滤器具有的所有依存关系。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.Configure<ErpSettings>(Configuration.GetSection("Erp"));
    services.AddTransient<CompanyFilter>();
}

要将过滤器应用于控制器操作,请使用ServiceFilterAttribute(Type)`

[HttpGet]
[ServiceFilter(typeof(CompanyFilter))]
public ActionResult<IEnumerable<string>> Get()
{
    return new string[] { ViewBag.ERPUrl };
}

在上面的代码中,您将看到我正在返回ViewBag.ERPUrl,这是因为您的ComapnyFilter已覆盖OnActionExecuting,该OnActionExecuted在调用操作之前已执行,而CompanyFilter在您的操作完成之后且响应返回给调用方之前将被调用。

IOptions<ErpSettings>的外观如下,您会注意到构造函数现在接受public class CompanyFilter : ActionFilterAttribute { private readonly ErpSettings erpSettings; public CompanyFilter(IOptions<ErpSettings> erpSettings) { this.erpSettings= erpSettings.Value; } public override void OnActionExecuting(ActionExecutingContext context) { if (context.Controller is Controller controller) controller.ViewBag.ERPUrl = erpSettings.Url; } }

{{1}}

所有这些完成后,这就是响应

API Response