2017-03-28 4 views
3

Ich versuche, einige meiner Dienste in der configure-Methode zu bekommen, so dass ich meine Datenbank einfacher mit ihnen.asp net Kern Anforderung Service in Configure-Methode gibt null

Also habe ich IServiceProvider injiziert in meinem Configure-Methode, aber jedes Mal, wenn ich tun: var service = serviceProvider.GetService<UserService>(); es gibt null zurück ...

Hier ist mein Code:

public class Startup 
    { 
     public Startup(IHostingEnvironment env) 
     { 
      var builder = new ConfigurationBuilder() 
       .SetBasePath(env.ContentRootPath) 
       .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 
       .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 

      builder.AddEnvironmentVariables(); 
      Configuration = builder.Build(); 
     } 

     public IConfigurationRoot Configuration { get; } 

     // This method gets called by the runtime. Use this method to add services to the container 
     public void ConfigureServices(IServiceCollection services) 
     { 

      services.AddDbContext<ApplicationDbContext>(options => 
       options.UseSqlServer(this.Configuration.GetConnectionString("DbConnectionString"))); 

      // Add framework services. 
      services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>().AddDefaultTokenProviders(); 
      string connection = this.Configuration.GetConnectionString("DbConnectionString"); 
      services.AddEntityFramework(); 
      services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connection)); 
      services.AddIdentity<ApplicationUser, IdentityRole>() 
       .AddEntityFrameworkStores<ApplicationDbContext>() 
       .AddDefaultTokenProviders(); 
      services.Configure<AppSettings>(this.Configuration.GetSection("AppSettings")); 

      services.AddScoped<IsAuthorized>(); 
      services.AddSingleton<UserManager<ApplicationUser>>(); 
      services.AddTransient<IUsersService, UserService>(); 

      services.AddMvc(config => { config.Filters.Add(typeof(SingletonUsers)); }); 
     } 

     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline 
     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider services) 
     { 
      loggerFactory.AddConsole(this.Configuration.GetSection("Logging")); 
      loggerFactory.AddDebug(); 

      app.UseMvc(); 

      // This returns the context. 
      var context = services.GetService<ApplicationDbContext>(); 

      // This returns null. 
      var userService = services.GetService<UserService>(); 

      // Can't work without the UserService 
      MyDbInitializer.Initialize(context, userService); 
     } 
    } 
+1

Sie benötigen Schnittstelle zu verwenden: 'var Userservice = services .GetService (); ' – Set

+0

Ja, es ist geschafft, danke! –

Antwort

3

wie Sie registriert UserService mit

services.AddTransient<IUsersService, UserService>(); 

statt

var userService = services.GetService<UserService>(); 

Sie benötigen für die Schnittstelle zu fragen:

var userService = services.GetService<IUserService>(); 
4

Als Alternative IServiceProvider zu injizieren , können Sie nur die Dienste als Parameter zu Configure anfordern:

public void Configure(
    IApplicationBuilder app, 
    IHostingEnvironment env, 
    ILoggerFactory loggerFactory, 
    ApplicationDbContext context, 
    IUserService userService) 
{ 

} 
+1

Es gibt keinen Grund, 'IServiceProvider' zu injizieren. Dies ist die richtige Antwort. – ssmith

1

IServiceProvider ist nicht beim Di/IoC registriert, da IServiceProviderder IoC/DI ist (oder ein Wrapper drum herum, wenn DI von Drittanbietern verwendet wird).

Sobald ein IServiceProvider erstellt wurde, kann die Abhängigkeitskonfiguration nicht mehr geändert werden (dies gilt für den Out of the Box-IoC).

Wenn Sie eine Abhängigkeit in Configure benötigen, sollten Sie diese Abhängigkeit als Methodenparameter übergeben (Methodeninjektion) und die Instanz abrufen. Wenn Sie weiterhin auf die IServiceProvider zugreifen müssen, können Sie dies tun, indem Sie app.ApplicationServices aufrufen. Wenn Sie app.ApplicationServices verwenden, lösen Sie den anwendungsweiten Container aus. Jeder auf diese Weise gelöste Service auf einmal oder auf Zeit bleibt aktiv, bis die Anwendung beendet wird. Dies liegt daran, dass während des Starts der Anwendung kein Bereichsbehälter vorhanden ist, sondern während einer Anforderung erstellt wird.

Das bedeutet, Sie haben einen Bereich innerhalb Configure Methode erstellen, instanziiert die Dienste, die Sie benötigen, rufen sie und dann die scoped Kontext verfügen, bevor Sie es verlassen.

// Example of EF DbContext seeding I use in my application 
using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope()) 
{ 
    using (var context = scope.ServiceProvider.GetRequiredService<MyDbContext>()) 
    { 
     if(context.Database.EnsureCreated()) 
     { 
      context.SeedAsync().Wait(); 
     } 
    } 
} 

Dies stellt sicher, dass alle Dienste übersichtlich sind und Sie keine Speicherlecks haben. Dies kann schwerwiegende Auswirkungen haben, wenn/DbContext ohne Erstellen eines Bereichscontainers initialisiert wird, z. B. wenn DbContext in ein Singleton umgewandelt wird (weil es vom übergeordneten Container aufgelöst wird) oder Speicherlecks verursacht werden, da Dienste, die im Anwendungsbereich aufgelöst werden, für die gesamte Lebensdauer aktiv bleiben Anwendung.

Verwandte Themen