ASP.NET 5 DI app设置外部控制器

时间:2016-04-28 02:25:04

标签: asp.net asp.net-mvc asp.net5

我可以在控制器中进行DI app设置,就像这样

 private IOptions<AppSettings> appSettings;
 public CompanyInfoController(IOptions<AppSettings> appSettings)
 {
     this.appSettings = appSettings;
 }

但是如何在我的自定义类中使用DI

  private IOptions<AppSettings> appSettings;
  public PermissionFactory(IOptions<AppSettings> appSetting)
  {
      this.appSettings = appSettings;
  }

我在Startup.cs中的注册是

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

4 个答案:

答案 0 :(得分:3)

&#34;适当&#34;方式

在DI中注册您的自定义类,就像在ConfigureServices方法中注册其他依赖项一样,例如:

services.AddTransient<PermissionFactory>();

(而不是AddTransient,您可以使用AddScoped或您需要的任何其他生命周期

然后将此依赖项添加到控制器的构造函数中:

public CompanyInfoController(IOptions<AppSettings> appSettings, PermissionFactory permFact)

现在,DI了解PermissionFactory,可以实例化它并将其注入您的控制器。

如果您想在PermissionFactory方法中使用Configure,只需将其添加到其参数列表中:

Configure(IApplicationBuilder app, PermissionFactory prov)

Aspnet会做它的魔法并在那里注入课程。

&#34;讨厌&#34;方式

如果你想在代码深处的某个地方实例化PermissionFactory,你也可以用一种讨厌的方式做到这一点 - 在IServiceProvider类中存储对Startup的引用:

internal static IServiceProvider ServiceProvider { get;set; }

Configure(IApplicationBuilder app, IServiceProvider prov) {
   ServiceProvider = prov;
   ...
}

现在您可以像这样访问它:

var factory = Startup.ServiceProvider.GetService<PermissionFactory>();

再一次,DI会负责将IOptions<AppSettings>注入PermissionFactory

Asp.Net 5 Docs in Dependency Injection

答案 1 :(得分:2)

我建议不要传递AppSettings。一个班级不应该依赖于某些含糊不清的东西 - 它应该完全取决于它需要什么,或者接近它。 ASP.NET Core可以更容易地摆脱依赖于AppSettings的旧模式。如果您的课程取决于AppSettings,那么您无法从构造函数中看到它依赖的内容。它可能取决于任何关键。如果它依赖于更具体的接口,那么它的依赖性更清晰,更明确,并且您可以在单元测试时模拟该接口。

您可以创建一个界面,其中包含您的类所需的特定设置(或不太具体但不太宽泛的设置)和实现它的类 - 例如,

    public interface IFooSettings
    {
        string Name { get; }
        IEnumerable Foos { get; }
    }

    public interface IFoo
    {
        string Color { get;  }
        double BarUnits { get;  }
    }

    public class FooSettings : IFooSettings
    {
        public string Name { get; set; }
        public List<Foo> FooList { get; set; }

        public IEnumerable Foos
        {
            get
            {
                if (FooList == null) FooList = new List<Foo>();
                return FooList.Cast<IFoo>();
            }
        }
    }

    public class Foo : IFoo
    {
        public string Color { get; set; }
        public double BarUnits { get; set; }
    }

然后添加一个.json文件,fooSettings.json:

    {
      "FooSettings": {
        "Name": "MyFooSettings",
        "FooList": [
          {
            "Color": "Red",
            "BarUnits": "1.5"
          },      {
            "Color": "Blue",
            "BarUnits": "3.14159'"
          },      {
            "Color": "Green",
            "BarUnits": "-0.99999"
          }
        ]
      }
    }

然后,在Startup()(在Startup.cs中)我们指定进入Configuration的内容,添加fooSettings.json:

    var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
        .AddJsonFile("config.json")
        .AddJsonFile($"config.{env.EnvironmentName}.json", optional: true)
        .AddJsonFile("fooSettings.json");

最后,在ConfigureServices()(也在Startup.cs中)告诉它加载FooSettings的实例,将其转换为IFooSetting s(因此属性显示为只读)并且为IFooSettings上的所有依赖项提供单个实例:

    var fooSettings = (IFooSettings)ConfigurationBinder.Bind<FooSettings>(
        Configuration.GetConfigurationSection("FooSettings"));
    services.AddInstance(typeof (IFooSettings), fooSettings);

现在你的类 - 控制器,过滤器或DI容器创建的任何其他东西 - 都可以依赖IFooSettings,它将从.json文件提供。但你可以模拟IFooSettings进行单元测试。

Original blog post - 它是我的,所以我不会剽窃。

答案 2 :(得分:1)

您也可以在非控制器类中执行依赖注入。

startup课程中

public class Startup
{
  public IConfigurationRoot Configuration { get; set; }

  public Startup(IHostingEnvironment env)
  {
        // Set up configuration sources.
     var builder = new ConfigurationBuilder()
             .AddJsonFile("appsettings.json")
             .AddEnvironmentVariables();
     Configuration = builder.Build();
  }
  public void ConfigureServices(IServiceCollection services)
  {
     // register other dependencies also here
     services.AddInstance<IConfiguration>(Configuration);     
  }
}

现在,在您的自定义类中,让构造函数接受IConfiguration

的实现
private IConfiguration configuration;
public PermissionFactory(IConfiguration configuration)
{
  this.configuration = configuration;
}
public void SomeMethod()
{
  var someSection = this.configuration.GetSection("SomeSection");
  var someValue= this.configuration.Get<string>("YourItem:SubItem");
}

答案 3 :(得分:0)

如果您希望DI对操作过滤器引用Action filters, service filters and type filters in ASP.NET 5 and MVC 6服务过滤器部件。