.NET 'e bağımlılık ekleme
.NET bağımlılık ekleme (dı) yazılım tasarımı modelini destekler, bu, sınıflar ve bunların bağımlılıkları arasında denetimin INVERSION (IoC) elde etmek için bir tekniktir. .NET ' te bağımlılık ekleme, yapılandırma, günlük oluşturma ve seçenekler düzeniyle birlikte birinci sınıf bir vatandaşlık.
Bağımlılık , başka bir nesnenin bağımlı olduğu bir nesnedir. Aşağıdaki sınıfı, MessageWriter Write diğer sınıfların bağımlı olduğu bir yöntemle inceleyin:
public class MessageWriter
{
public void Write(string message)
{
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
Bir sınıf, MessageWriter yöntemini kullanmak için sınıfının bir örneğini oluşturabilir Write . Aşağıdaki örnekte, MessageWriter sınıfı sınıfının bir bağımlılığı olur Worker :
public class Worker : BackgroundService
{
private readonly MessageWriter _messageWriter = new MessageWriter();
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
await Task.Delay(1000, stoppingToken);
}
}
}
Sınıfı oluşturur ve doğrudan MessageWriter sınıfa bağlıdır. Önceki örnekte olduğu gibi sabit kodlu bağımlılıklar sorunlu olur ve aşağıdaki nedenlerden dolayı kaçınılması gerekir:
MessageWriterFarklı bir uygulamayla değiştirmek için,Workersınıfın değiştirilmesi gerekir.MessageWriterBağımlılıkları varsa, sınıf tarafından da yapılandırılmalıdırWorker. Uygulamasına bağlı olarak, birden çok sınıfı olan büyük bir projedeMessageWriteryapılandırma kodu uygulama genelinde dağılmış hale gelir.- Bu uygulamanın birim testi zordur. Uygulamanın
MessageWriterBu yaklaşım ile mümkün olmayan bir sahte veya saplama sınıfı kullanması gerekir.
Bağımlılık ekleme bu sorunları şu şekilde giderir:
- Bağımlılık uygulamasını soyutlamak için bir arabirim veya temel sınıf kullanımı.
- Bir hizmet kapsayıcısına bağımlılığın kaydı. .NET, yerleşik bir hizmet kapsayıcısı sağlar IServiceProvider . Hizmetler genellikle uygulamanın başlangıcında kaydedilir ve bir öğesine eklenir IServiceCollection . Tüm hizmetler eklendikten sonra, BuildServiceProvider hizmet kapsayıcısını oluşturmak için kullanırsınız.
- Hizmetin kullanıldığı sınıf oluşturucusuna ekleme . Çerçeve, bağımlılığın bir örneğini oluşturma ve artık gerekli olmadığında bu uygulamayı atma sorumluluğunu alır.
Örnek olarak, IMessageWriter arabirim Write yöntemini tanımlar:
namespace DependencyInjection.Example;
public interface IMessageWriter
{
void Write(string message);
}
Bu arabirim somut bir tür tarafından uygulanır, MessageWriter :
namespace DependencyInjection.Example;
public class MessageWriter : IMessageWriter
{
public void Write(string message)
{
Console.WriteLine($"MessageWriter.Write(message: \"{message}\")");
}
}
Örnek kod, IMessageWriter hizmeti somut tür ile kaydeder MessageWriter . AddScopedYöntemi, hizmeti tek bir isteğin ömrü olan kapsamlı bir yaşam süresine kaydeder. Hizmet yaşam süreleri Bu makalenin ilerleyen kısımlarında açıklanmıştır.
namespace DependencyInjection.Example;
class Program
{
static Task Main(string[] args) =>
CreateHostBuilder(args).Build().RunAsync();
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddHostedService<Worker>()
.AddScoped<IMessageWriter, MessageWriter>());
}
Örnek uygulamada, IMessageWriter hizmet istenir ve yöntemi çağırmak için kullanılır Write :
namespace DependencyInjection.Example;
public class Worker : BackgroundService
{
private readonly IMessageWriter _messageWriter;
public Worker(IMessageWriter messageWriter) =>
_messageWriter = messageWriter;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
await Task.Delay(1000, stoppingToken);
}
}
}
Dı modelini kullanarak çalışan hizmeti:
- Somut türü kullanmaz
MessageWriter, yalnızcaIMessageWriteronu uygulayan arabirim. Bu, denetleyicinin, denetleyiciyi değiştirmeden kullandığı uygulamayı değiştirmeyi kolaylaştırır. - Bir örneği oluşturmaz
MessageWriter, bu, dı kapsayıcısı tarafından oluşturulur.
Arabirim uygulanması, IMessageWriter yerleşik günlük API 'si kullanılarak artırılabilir:
namespace DependencyInjection.Example;
public class LoggingMessageWriter : IMessageWriter
{
private readonly ILogger<LoggingMessageWriter> _logger;
public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) =>
_logger = logger;
public void Write(string message) =>
_logger.LogInformation(message);
}
Updated ConfigureServices yöntemi yeni IMessageWriter uygulamayı kaydeder:
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddHostedService<Worker>()
.AddScoped<IMessageWriter, LoggingMessageWriter>());
LoggingMessageWriterILogger<TCategoryName>, oluşturucuda istediği öğesine bağlıdır. ILogger<TCategoryName>Framework tarafından sağlanmış bir hizmettir.
Bağımlılık ekleme işlemini zincirleme bir biçimde kullanmak olağan dışı değildir. Her istenen bağımlılık, kendi bağımlılıklarını ister. Kapsayıcı grafikteki bağımlılıkları çözer ve tamamen çözümlenen hizmeti döndürür. Çözümlenmesi gereken, genellikle bağımlılık ağacı, bağımlılık grafiği veya nesne grafiği olarak adlandırılan toplu bağımlılıklar kümesi.
Kapsayıcı, ILogger<TCategoryName> (genel) açık türlerdenyararlanarak çözümlenir, her (genel) oluşturulan türükaydetme ihtiyacını ortadan kaldırır.
Bağımlılık ekleme terminolojisi ile bir hizmet:
- Genellikle hizmet gibi diğer nesnelere hizmet sağlayan bir nesnedir
IMessageWriter. - Bir Web hizmetiyle ilgili değildir, ancak hizmet bir Web hizmeti kullanabilir.
Çerçeve, güçlü bir günlük sistemi sağlar. IMessageWriterYukarıdaki örneklerde gösterilen uygulamalar, günlüğü uygulamamak için değil temel dı 'yi göstermek için yazılmıştır. Çoğu uygulamanın Günlükçüler yazması gerekmez. Aşağıdaki kod, yalnızca Worker ' ın ConfigureServices barındırılan bir hizmet olarak kaydedilmesini gerektiren varsayılan günlük kaydını kullanmayı göstermektedir AddHostedService :
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger) =>
_logger = logger;
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
Yukarıdaki kodu kullanarak, ConfigureServices Framework tarafından günlüğe kaydetme sağlandığı için güncelleştirmeniz gerekmez.
Birden çok Oluşturucu bulma kuralı
Bir tür birden çok Oluşturucu tanımlıyorsa, hizmet sağlayıcının hangi oluşturucunun kullanılacağını belirlemek için mantığı vardır. Türlerin dı-çözülebilir olduğu en fazla parametre içeren Oluşturucu seçilidir. Aşağıdaki C# örnek hizmetini göz önünde bulundurun:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(ILogger<ExampleService> logger)
{
// omitted for brevity
}
public ExampleService(FooService fooService, BarService barService)
{
// omitted for brevity
}
}
Yukarıdaki kodda, günlük kaydının eklendiğini ve hizmet sağlayıcısından FooService BarService çözümlenediğine, ancak türleri olmadığını varsayın. Parametresini içeren Oluşturucu, ILogger<ExampleService> örneği çözümlemek için kullanılır ExampleService . Daha fazla parametre tanımlayan bir Oluşturucu olsa da, FooService ve BarService türleri yok çözülebilir değildir.
Oluşturucular bulunurken belirsizlik olduğunda bir özel durum oluşturulur. Aşağıdaki C# örnek hizmetini göz önünde bulundurun:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(ILogger<ExampleService> logger)
{
// omitted for brevity
}
public ExampleService(IOptions<ExampleService> options)
{
// omitted for brevity
}
}
Uyarı
ExampleServiceBelırsız dı-çözümlenebilen tür parametrelerine sahip kod bir özel durum oluşturur. Bunu yapmazsanız, "belirsiz dı-çözülebilir türler" tarafından ne olduğunu göstermek için tasarlanmıştır.
Yukarıdaki örnekte, üç Oluşturucu vardır. İlk Oluşturucu parametresiz olur ve hizmet sağlayıcısından hiçbir hizmet gerektirmez. Her iki günlük ve seçeneğin de dı kapsayıcısına eklendiğini ve dı ile çözülebilir hizmetler olduğunu varsayalım. DI kapsayıcısı türü çözümlemeye çalıştığında ExampleService , iki Oluşturucu belirsiz olduğu için bir özel durum oluşturur. Bu örnekte, bunun yerine hem dı-çözülebilir türler kabul eden bir Oluşturucu tanımlayarak belirsizliğe engel olabilirsiniz:
public class ExampleService
{
public ExampleService()
{
}
public ExampleService(
ILogger<ExampleService> logger,
IOptions<ExampleService> options)
{
// omitted for brevity
}
}
Uzantı yöntemleriyle hizmet gruplarını kaydet
Microsoft uzantıları, bir grup ilgili hizmeti kaydetmek için bir kural kullanır. Kural, Add{GROUP_NAME} bir Framework özelliği için gereken tüm hizmetleri kaydetmek için tek bir genişletme yöntemi kullanmaktır. Örneğin, AddOptions genişletme yöntemi, seçenekleri kullanmak için gereken tüm hizmetleri kaydeder.
Framework tarafından sunulan hizmetler
ConfigureServicesYöntemi, platform özellikleri dahil olmak üzere uygulamanın kullandığı hizmetleri kaydeder. Başlangıçta, IServiceCollection için belirtilen, ConfigureServices konağın nasıl yapılandırıldığınabağlı olarak Framework tarafından tanımlanan hizmetlere sahiptir. .NET şablonlarına dayalı uygulamalar için Framework yüzlerce hizmeti kaydeder.
Aşağıdaki tabloda, bu çerçeve kayıtlı hizmetlerinin küçük bir örneği listelenmektedir:
Hizmet yaşam süreleri
Hizmetler aşağıdaki yaşam sürelerinin biriyle kaydedilebilir:
- Larsa
- Yayıl
- Adet
Aşağıdaki bölümlerde, önceki yaşam sürelerinin her biri açıklanır. Kayıtlı her hizmet için uygun bir yaşam süresi seçin.
Larsa
Geçici ömür Hizmetleri, hizmet kapsayıcısından her istenilişinde oluşturulur. Bu ömür, hafif ve durumsuz hizmetler için en iyi şekilde kullanılır. Geçici Hizmetleri ile kaydedin AddTransient .
İstekleri işleyen uygulamalarda, geçici hizmetler isteğin sonuna atıldı.
Yayıl
Web uygulamaları için kapsamlı bir yaşam süresi, hizmetlerin istemci isteği başına bir kez oluşturulduğunu belirtir (bağlantı). Kapsamlı hizmetleri ile kaydedin AddScoped .
İstekleri işleyen uygulamalarda, kapsamlı hizmetler isteğin sonuna atıldı.
Entity Framework Core kullanılırken, AddDbContext genişletme yöntemi, DbContext Varsayılan olarak kapsamlı yaşam süresine sahip türleri kaydeder.
Not
Kapsamlı bir hizmeti tek bir hizmetten çözmeyin ve örneğin geçici bir hizmet aracılığıyla dolaylı olarak geçmemeye dikkat edin. Bu, sonraki istekleri işlerken hizmetin yanlış duruma gelmesine neden olabilir. Şunları yapabilirsiniz:
- Tek bir hizmeti kapsamlı veya geçici bir hizmetten çözümleyin.
- Kapsamlı bir hizmeti başka bir kapsamlı veya geçici hizmetten çözün.
Varsayılan olarak, geliştirme ortamında, bir hizmetin daha uzun bir yaşam süresine sahip başka bir hizmetten çözülmesi bir özel durum oluşturur. Daha fazla bilgi için bkz. kapsam doğrulaması.
Adet
Tek yaşam süresi Hizmetleri şu şekilde oluşturulur:
- İlk kez istenirler.
- Geliştirici tarafından doğrudan kapsayıcıya bir uygulama örneği sağlarken. Bu yaklaşım nadiren gereklidir.
Bağımlılık ekleme kapsayıcısından gelen hizmet uygulamasının sonraki tüm istekleri aynı örneği kullanır. Uygulama tek davranış gerektiriyorsa, hizmet kapsayıcısının hizmetin ömrünü yönetmesine izin verin. Tek tasarım modelini uygulamayın ve tek bir atma kodu sağlayın. Hizmetler, kapsayıcıyı hizmetten çözümleyen kodla hiçbir şekilde atılmamalıdır. Bir tür veya fabrika tek bir olarak kayıtlıysa, kapsayıcı kendiliğinden otomatik olarak atar.
İle Singleton hizmetlerini kaydettirin AddSingleton . Tek hizmetler iş parçacığı güvenli olmalıdır ve genellikle durum bilgisiz hizmetlerde kullanılır.
İstekleri işleyen uygulamalarda, uygulama kapatılırken bırakıldığında tek hizmetler silinir ServiceProvider . Uygulama kapatılıncaya kadar bellek yayımlanmadığı için, tek bir hizmetle bellek kullanımını göz önünde bulundurun.
Hizmet kayıt yöntemleri
Framework, belirli senaryolarda yararlı olan hizmet kayıt uzantısı yöntemleri sağlar:
| Yöntem | Automatic object elden |
Birden çok uygulamalar |
Geçiş bağımsız değişkenleri |
|---|---|---|---|
Add{LIFETIME}<{SERVICE}, {IMPLEMENTATION}>()Örnek: services.AddSingleton<IMyDep, MyDep>(); |
Yes | Yes | Hayır |
Add{LIFETIME}<{SERVICE}>(sp => new {IMPLEMENTATION})Örnekler: services.AddSingleton<IMyDep>(sp => new MyDep());services.AddSingleton<IMyDep>(sp => new MyDep(99)); |
Yes | Yes | Yes |
Add{LIFETIME}<{IMPLEMENTATION}>()Örnek: services.AddSingleton<MyDep>(); |
Yes | Hayır | Hayır |
AddSingleton<{SERVICE}>(new {IMPLEMENTATION})Örnekler: services.AddSingleton<IMyDep>(new MyDep());services.AddSingleton<IMyDep>(new MyDep(99)); |
Hayır | Yes | Yes |
AddSingleton(new {IMPLEMENTATION})Örnekler: services.AddSingleton(new MyDep());services.AddSingleton(new MyDep(99)); |
Hayır | Hayır | Yes |
Tür çıkarma hakkında daha fazla bilgi için Hizmetler 'In aktiften çıkarılması bölümüne bakın.
Hizmeti yalnızca bir uygulama türüyle kaydetmek, bu hizmeti aynı uygulama ve hizmet türüyle kaydetmeye eşdeğerdir. Bu, bir hizmetin birden çok uygulamasının açık bir hizmet türü kullanmayan yöntemler kullanılarak kaydedilamamasının nedenleridir. Bu yöntemler bir hizmetin birden fazla örneğini kaydedebilir, ancak hepsi aynı uygulama türüne sahip olur.
Yukarıdaki hizmet kayıt yöntemlerinden herhangi biri aynı hizmet türünün birden çok hizmet örneğini kaydetmek için kullanılabilir. Aşağıdaki örnekte, AddSingleton hizmet türü olarak ile iki kez çağırılır IMessageWriter . İçin ikinci çağrı, AddSingleton olarak çözümlendikten önceki bir öncekini geçersiz kılar IMessageWriter ve aracılığıyla birden çok hizmet çözümlendiğinde bir öncekini ekler IEnumerable<IMessageWriter> . Hizmetler, ile çözümlendiklerinde kaydedildikleri sırada görüntülenir IEnumerable<{SERVICE}> .
using ConsoleDI.IEnumerableExample;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ConsoleDI.Example;
class Program
{
static Task Main(string[] args)
{
using IHost host = CreateHostBuilder(args).Build();
_ = host.Services.GetService<ExampleService>();
return host.RunAsync();
}
static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddSingleton<IMessageWriter, ConsoleMessageWriter>()
.AddSingleton<IMessageWriter, LoggingMessageWriter>()
.AddSingleton<ExampleService>());
}
Önceki örnek kaynak kodu, öğesinin iki uygulamalarını kaydeder IMessageWriter .
using System.Diagnostics;
namespace ConsoleDI.IEnumerableExample;
public class ExampleService
{
public ExampleService(
IMessageWriter messageWriter,
IEnumerable<IMessageWriter> messageWriters)
{
Trace.Assert(messageWriter is LoggingMessageWriter);
var dependencyArray = messageWriters.ToArray();
Trace.Assert(dependencyArray[0] is ConsoleMessageWriter);
Trace.Assert(dependencyArray[1] is LoggingMessageWriter);
}
}
ExampleServiceİki Oluşturucu parametresini tanımlar; tek bir IMessageWriter ve bir IEnumerable<IMessageWriter> . Tek, kayıtlı IMessageWriter olan en son uygulama, IEnumerable<IMessageWriter> Tüm kayıtlı uygulamaları temsil eder.
Framework Ayrıca, TryAdd{LIFETIME} yalnızca kayıtlı bir uygulama olmadığında hizmeti kaydeden genişletme yöntemleri de sağlar.
Aşağıdaki örnekte, AddSingleton ConsoleMessageWriter için bir uygulama olarak Yazmaçları çağrısı IMessageWriter . TryAddSingleton IMessageWriter Zaten kayıtlı bir uygulamaya sahip olduğundan, çağrısının bir etkisi yoktur:
services.AddSingleton<IMessageWriter, ConsoleMessageWriter>();
services.TryAddSingleton<IMessageWriter, LoggingMessageWriter>();
TryAddSingletonZaten eklendiği için hiçbir etkisi yoktur ve "TRY" başarısız olur. Aşağıdaki işlemi yapılır ExampleService :
public class ExampleService
{
public ExampleService(
IMessageWriter messageWriter,
IEnumerable<IMessageWriter> messageWriters)
{
Trace.Assert(messageWriter is ConsoleMessageWriter);
Trace.Assert(messageWriters.Single() is ConsoleMessageWriter);
}
}
Daha fazla bilgi için bkz.
TryAddEnumerable (ServiceDescriptor) yöntemleri, yalnızca aynı türde bir uygulama olmadığında hizmeti kaydeder. Aracılığıyla birden çok hizmet çözümlenir IEnumerable<{SERVICE}> . Hizmetleri kaydederken, aynı türden biri zaten eklenmediyse bir örnek ekleyin. Kitaplık yazarları TryAddEnumerable , kapsayıcıda bir uygulamanın birden çok kopyasını kaydetmemek için kullanır.
Aşağıdaki örnekte, TryAddEnumerable MessageWriter için bir uygulama olarak kaydeden ilk çağrı IMessageWriter1 . İçin ikinci çağrı kaydettirir MessageWriter IMessageWriter2 . IMessageWriter1Zaten kayıtlı bir uygulamasına sahip olduğundan, üçüncü çağrının etkisi yoktur MessageWriter :
public interface IMessageWriter1 { }
public interface IMessageWriter2 { }
public class MessageWriter : IMessageWriter1, IMessageWriter2
{
}
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter1, MessageWriter>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter2, MessageWriter>());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMessageWriter1, MessageWriter>());
Hizmet kaydı, aynı türde birden çok uygulama kaydedilirken genellikle sıralı olarak bağımsızdır.
IServiceCollection bir ServiceDescriptor nesne koleksiyonudur. Aşağıdaki örnek, oluşturma ve ekleme yoluyla bir hizmetin nasıl kaydedileceği gösterilmektedir ServiceDescriptor :
string secretKey = Configuration["SecretKey"];
var descriptor = new ServiceDescriptor(
typeof(IMessageWriter),
_ => new DefaultMessageWriter(secretKey),
ServiceLifetime.Transient);
services.Add(descriptor);
Yerleşik Add{LIFETIME} Yöntemler aynı yaklaşımı kullanır. Örneğin, bkz. Addkapsamlıdır kaynak kodu.
Oluşturucu Ekleme davranışı
Hizmetler, kullanılarak çözülebilir:
- IServiceProvider
- ActivatorUtilities:
- Kapsayıcıda kayıtlı olmayan nesneler oluşturur.
- Bazı Framework özellikleriyle kullanılır.
Oluşturucular bağımlılık ekleme tarafından sağlanmayan bağımsız değişkenleri kabul edebilir, ancak bağımsız değişkenlerin varsayılan değerleri ataması gerekir.
Hizmetler veya tarafından çözümlendiğinde IServiceProvider ActivatorUtilities , Oluşturucu Ekleme ortak bir Oluşturucu gerektirir.
Hizmetler tarafından çözümlendiğinde ActivatorUtilities , Oluşturucu ekleme yalnızca bir adet geçerli oluşturucunun var olmasını gerektirir. Oluşturucu aşırı yüklemeleri desteklenir, ancak bağımsız değişkenleri bağımlılık ekleme tarafından yerine yalnızca bir aşırı yükleme bulunabilir.
Kapsam doğrulaması
Uygulama Development ortamda çalışır ve konağı oluşturmak Için Createdefaultbuilder ' ı çağırırsa, varsayılan hizmet sağlayıcısı şunları doğrulamak için denetimler gerçekleştirir:
- Kapsamlı hizmetler kök hizmet sağlayıcısından çözümlenmez.
- Kapsamlı hizmetler tekton 'a eklenmiş değildir.
Kök hizmet sağlayıcısı BuildServiceProvider çağrıldığında oluşturulur. Kök hizmet sağlayıcısının ömrü, sağlayıcının uygulamayla başladığı ve uygulama kapandığında bırakıldığı uygulamanın ömrüne karşılık gelir.
Kapsamlı hizmetler kendilerini oluşturan kapsayıcı tarafından atılmış. Kök kapsayıcıda kapsamlı bir hizmet oluşturulduysa, hizmetin ömrü, uygulama kapandığında yalnızca kök kapsayıcı tarafından atıldığı için etkin bir şekilde tek bir yükseltilir. Hizmet kapsamlarını doğrulamak, çağrıldığında bu durumları yakalar BuildServiceProvider .
Kapsam senaryoları
IServiceScopeFactoryher zaman tekli olarak kaydedilir, ancak IServiceProvider içeren sınıfın yaşam süresine göre değişiklik gösterebilir. Örneğin, bir kapsamdan hizmetleri çözümler ve bu hizmetlerden herhangi biri bir IServiceProvider alırsanız, kapsamlı bir örnek olur.
uygulamaları içinde , gibi kapsamındaki hizmetlere IHostedService ulaşmak BackgroundService için, oluşturucu ekleme yoluyla hizmet bağımlılıklarını eklemez. Bunun yerine, IServiceScopeFactory , bir kapsam oluşturun ve ardından uygun hizmet ömrünü kullanmak için kapsamdan bağımlılıkları çözümlenin.
namespace WorkerScope.Example;
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
public Worker(ILogger<Worker> logger, IServiceScopeFactory serviceScopeFactory) =>
(_logger, _serviceScopeFactory) = (logger, serviceScopeFactory);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using (IServiceScope scope = _serviceScopeFactory.CreateScope())
{
try
{
_logger.LogInformation(
"Starting scoped work, provider hash: {hash}.",
scope.ServiceProvider.GetHashCode());
var store = scope.ServiceProvider.GetRequiredService<IObjectStore>();
var next = await store.GetNextAsync();
_logger.LogInformation("{next}", next);
var processor = scope.ServiceProvider.GetRequiredService<IObjectProcessor>();
await processor.ProcessAsync(next);
_logger.LogInformation("Processing {name}.", next.Name);
var relay = scope.ServiceProvider.GetRequiredService<IObjectRelay>();
await relay.RelayAsync(next);
_logger.LogInformation("Processed results have been relayed.");
var marked = await store.MarkAsync(next);
_logger.LogInformation("Marked as processed: {next}", marked);
}
finally
{
_logger.LogInformation(
"Finished scoped work, provider hash: {hash}.{nl}",
scope.ServiceProvider.GetHashCode(), Environment.NewLine);
}
}
}
}
}
Yukarıdaki kodda, uygulama çalışırken arka plan hizmeti:
- , 'a IServiceScopeFactory bağlıdır.
- Ek hizmetleri IServiceScope çözümlemek için bir oluşturur.
- Kapsamlı hizmetleri tüketim için çözümler.
- Nesneleri işlemeye, geçişe dönüştürmeye çalışır ve son olarak işlenmiş olarak işaretler.
Örnek kaynak kodundan, uygulamasının kapsamlı hizmet yaşam IHostedService sürelerinden nasıl yararlanabileceklerini görebilir.
Ayrıca bkz.
- .NET'te bağımlılık ekleme kullanma
- Bağımlılık ekleme yönergeleri
- ASP.NET Core'a bağımlılık ekleme
- DI uygulaması geliştirme için NDC Konferans Desenleri
- Açık bağımlılıklar ilkesi
- Denetim kapsayıcılarının ve bağımlılık ekleme deseninin ters çevirmesi (Martin Fowler)
- Di hataları, github.com/dotnet/extensions oluşturulmelidir