ASP.NET 5(vNext))の変更を学習し始め、「モデル」のメソッドなどでIServiceProviderを取得する方法を見つけることができません
public class Entity
{
public void DoSomething()
{
var dbContext = ServiceContainer.GetService<DataContext>(); //Where is ServiceContainer or something like that ?
}
}
起動時にサービスを構成しますが、すべてのサービスコレクションが残っているのはIServiceProviderですか?
Microsoft.Extensions.DependencyInjection
ジェネリックにアクセスするための名前空間
GetService<T>();
で使用される拡張メソッド
IServiceProvider
また、ASP.NET 5のコントローラーにサービスを直接注入できることに注意してください。以下の例を参照してください。
public interface ISomeService
{
string ServiceValue { get; set; }
}
public class ServiceImplementation : ISomeService
{
public ServiceImplementation()
{
ServiceValue = "Injected from Startup";
}
public string ServiceValue { get; set; }
}
Startup.cs
public void ConfigureService(IServiceCollection services)
{
...
services.AddSingleton<ISomeService, ServiceImplementation>();
}
HomeController
using Microsoft.Extensions.DependencyInjection;
...
public IServiceProvider Provider { get; set; }
public ISomeService InjectedService { get; set; }
public HomeController(IServiceProvider provider, ISomeService injectedService)
{
Provider = provider;
InjectedService = Provider.GetService<ISomeService>();
}
いずれかのアプローチを使用して、サービスにアクセスできます。 Startup.csの追加のサービス拡張機能
AddInstance<IService>(new Service())
常に単一のインスタンスが与えられます。最初のオブジェクト作成はユーザーの責任です。
AddSingleton<IService, Service>()
単一のインスタンスが作成され、シングルトンのように機能します。
AddTransient<IService, Service>()
新しいインスタンスは、挿入されるたびに作成されます。
AddScoped<IService, Service>()
現在のHTTP Requestスコープ内に単一のインスタンスが作成されます。現在のスコープコンテキストのシングルトンと同等です。
2018年10月18日に更新
エンティティ(またはモデル)がサービスにアクセスするのは良い考えではないと思います。
一方、コントローラーは、コンストラクターで登録されたサービスにアクセスできるので、心配する必要はありません。
public class NotifyController : Controller
{
private static IEmailSender emailSender = null;
protected static ISessionService session = null;
protected static IMyContext dbContext = null;
protected static IHostingEnvironment hostingEnvironment = null;
public NotifyController(
IEmailSender mailSenderService,
IMyContext context,
IHostingEnvironment env,
ISessionService sessionContext)
{
emailSender = mailSenderService;
dbContext = context;
hostingEnvironment = env;
session = sessionContext;
}
}
aSP.NET Coreの例のように、GetServiceの代わりにGetRequiredServiceを使用しますチュートリアル( https://docs.Microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/working-with-sql )
メソッドに関するドキュメント:
using Microsoft.Extensions.DependencyInjection;
using (var context = new ApplicationDbContext(serviceProvicer.GetRequiredService<DbContextOptions<ApplicationDbContext>>()))
一般的に、DIにその機能を実行させ、それを注入します。
_public class Entity
{
private readonly IDataContext dbContext;
// The DI will auto inject this for you
public class Entity(IDataContext dbContext)
{
this.dbContext = dbContext;
}
public void DoSomething()
{
// dbContext is already populated for you
var something = dbContext.Somethings.First();
}
}
_
ただし、Entity
は、Controller
やViewComponent
のように自動的にインスタンス化する必要があります。このdbContext
が利用できない場所からこれを手動でインスタンス化する必要がある場合、これを行うことができます。
_using Microsoft.Extensions.PlatformAbstractions;
public class Entity
{
private readonly IDataContext dbContext;
public class Entity()
{
this.dbContext = (IDataContext)CallContextServiceLocator.Locator.ServiceProvider
.GetService(typeof(IDataContext));
}
public void DoSomething()
{
var something = dbContext.Somethings.First();
}
}
_
しかし、単に強調するために、これはアンチパターンと見なされており、どうしても必要な場合を除いて避けるべきです。そして...いくつかのパターンの人々を本当に混乱させるリスクがある...他のすべてが失敗した場合、ヘルパークラスまたは何かに_static IContainer
_を追加し、StartUp
クラスにそれを割り当てることができますConfigureServices
メソッド:MyHelper.DIContainer = builder.Build();
そして、これは本当にい方法ですが、動作させる必要がある場合もあります。
サービスをインラインで取得する代わりに、コンストラクタに挿入してみてください。
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient(typeof(DataContext));
}
}
public class Entity
{
private DataContext _context;
public Entity(DataContext context)
{
_context = context;
}
public void DoSomething()
{
// use _context here
}
}
また、アプリケーションがDbContextのインスタンスを共有する方法に大きな影響を与えるため、AddTransient
の意味を調べることをお勧めします。これは Dependency Injection と呼ばれるパターンです。慣れるまでには時間がかかりますが、一度戻ってしまうことはありません。
OPは混乱していると思います。エンティティは可能な限り「薄く」する必要があります。ロジックやナビゲーションプロパティ以外の外部参照を含めないようにする必要があります。エンティティ自体からロジックを抽象化するのに役立つリポジトリパターンなどの一般的なパターンを検索します