Öğretici: .NET'te bağımlılık ekleme kullanma
Bu öğreticide .NET'te bağımlılık eklemenin (DI) nasıl kullanılacağı gösterilmektedir. Microsoft Uzantıları ile DI, hizmetleri ekleyip içinde IServiceCollectionyapılandırarak yönetilir. IHost Arabirimi, tüm kayıtlı hizmetlerin kapsayıcısı işlevi gören örneği kullanıma sunarIServiceProvider.
Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:
- Bağımlılık ekleme kullanan bir .NET konsol uygulaması oluşturma
- Genel Konak oluşturma ve yapılandırma
- Çeşitli arabirimler ve karşılık gelen uygulamalar yazma
- DI için hizmet ömrünü ve kapsam belirlemeyi kullanma
Önkoşullar
- .NET Core 3.1 SDK veya üzeri.
- Yeni .NET uygulamaları oluşturma ve NuGet paketlerini yükleme hakkında bilgi.
Yeni konsol uygulaması oluşturma
dotnet new komutunu veya IDE yeni proje sihirbazını kullanarak ConsoleDI adlı yeni bir .NET konsol uygulaması oluşturun.Example. Projeye Microsoft.Extensions.Hosting NuGet paketini ekleyin.
Yeni konsol uygulaması proje dosyanız aşağıdakine benzer olmalıdır:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<RootNamespace>ConsoleDI.Example</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
</Project>
Önemli
Bu örnekte, uygulamayı derlemek ve çalıştırmak için Microsoft.Extensions.Hosting NuGet paketi gereklidir. Bazı meta paketler paketi içerebilir Microsoft.Extensions.Hosting
ve bu durumda açık bir paket başvurusu gerekmez.
Arabirim ekleme
Bu örnek uygulamada bağımlılık eklemenin hizmet ömrünü nasıl işlediğini öğreneceksiniz. Farklı hizmet ömürlerini temsil eden çeşitli arabirimler oluşturacaksınız. Proje kök dizinine aşağıdaki arabirimleri ekleyin:
IReportServiceLifetime.cs
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleDI.Example;
public interface IReportServiceLifetime
{
Guid Id { get; }
ServiceLifetime Lifetime { get; }
}
Arabirim IReportServiceLifetime
aşağıdakileri tanımlar:
Guid Id
Hizmetin benzersiz tanımlayıcısını temsil eden özellik.- ServiceLifetime Hizmet ömrünü temsil eden bir özellik.
Service.csExampleTransient
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleDI.Example;
public interface IExampleTransientService : IReportServiceLifetime
{
ServiceLifetime IReportServiceLifetime.Lifetime => ServiceLifetime.Transient;
}
Service.csExampleScoped
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleDI.Example;
public interface IExampleScopedService : IReportServiceLifetime
{
ServiceLifetime IReportServiceLifetime.Lifetime => ServiceLifetime.Scoped;
}
Service.csExampleSingleton
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleDI.Example;
public interface IExampleSingletonService : IReportServiceLifetime
{
ServiceLifetime IReportServiceLifetime.Lifetime => ServiceLifetime.Singleton;
}
öğesinin tüm alt arabirimleri IReportServiceLifetime
, öğesini varsayılan değerle açıkça uygular IReportServiceLifetime.Lifetime
. Örneğin, IExampleTransientService
açıkça değeriyle ServiceLifetime.Transient
uygularIReportServiceLifetime.Lifetime
.
Varsayılan uygulamaları ekleme
Örnek uygulamaların tümü, sonucuyla Guid.NewGuid()kendi Id
özelliğini başlatır. Çeşitli hizmetler için aşağıdaki varsayılan uygulama sınıflarını proje kök dizinine ekleyin:
ExampleTransientService.cs
namespace ConsoleDI.Example;
internal sealed class ExampleTransientService : IExampleTransientService
{
Guid IReportServiceLifetime.Id { get; } = Guid.NewGuid();
}
ExampleScopedService.cs
namespace ConsoleDI.Example;
internal sealed class ExampleScopedService : IExampleScopedService
{
Guid IReportServiceLifetime.Id { get; } = Guid.NewGuid();
}
ExampleSingletonService.cs
namespace ConsoleDI.Example;
internal sealed class ExampleSingletonService : IExampleSingletonService
{
Guid IReportServiceLifetime.Id { get; } = Guid.NewGuid();
}
Her uygulama olarak internal sealed
tanımlanır ve ilgili arabirimini uygular. Örneğin, ExampleSingletonService
uygular IExampleSingletonService
.
DI gerektiren bir hizmet ekleme
Konsol uygulamasına hizmet işlevi gören aşağıdaki hizmet ömrü muhabir sınıfını ekleyin:
ServiceLifetimeReporter.cs
namespace ConsoleDI.Example;
internal sealed class ServiceLifetimeReporter(
IExampleTransientService transientService,
IExampleScopedService scopedService,
IExampleSingletonService singletonService)
{
public void ReportServiceLifetimeDetails(string lifetimeDetails)
{
Console.WriteLine(lifetimeDetails);
LogService(transientService, "Always different");
LogService(scopedService, "Changes only with lifetime");
LogService(singletonService, "Always the same");
}
private static void LogService<T>(T service, string message)
where T : IReportServiceLifetime =>
Console.WriteLine(
$" {typeof(T).Name}: {service.Id} ({message})");
}
, ServiceLifetimeReporter
yukarıda belirtilen hizmet arabirimlerinin her birini (, , IExampleScopedService
ve IExampleSingletonService
) IExampleTransientService
gerektiren bir oluşturucu tanımlar. nesnesi, tüketicinin belirli lifetimeDetails
bir parametreyle hizmette raporlama yapmasını sağlayan tek bir yöntemi kullanıma sunar. Çağrıldığında, ReportServiceLifetimeDetails
yöntemi her hizmetin benzersiz tanımlayıcısını hizmet ömrü iletisiyle günlüğe kaydeder. Günlük iletileri hizmet ömrünü görselleştirmeye yardımcı olur.
DI için hizmetleri kaydetme
Program.cs aşağıdaki kodla güncelleştirin:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ConsoleDI.Example;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddTransient<IExampleTransientService, ExampleTransientService>();
builder.Services.AddScoped<IExampleScopedService, ExampleScopedService>();
builder.Services.AddSingleton<IExampleSingletonService, ExampleSingletonService>();
builder.Services.AddTransient<ServiceLifetimeReporter>();
using IHost host = builder.Build();
ExemplifyServiceLifetime(host.Services, "Lifetime 1");
ExemplifyServiceLifetime(host.Services, "Lifetime 2");
await host.RunAsync();
static void ExemplifyServiceLifetime(IServiceProvider hostProvider, string lifetime)
{
using IServiceScope serviceScope = hostProvider.CreateScope();
IServiceProvider provider = serviceScope.ServiceProvider;
ServiceLifetimeReporter logger = provider.GetRequiredService<ServiceLifetimeReporter>();
logger.ReportServiceLifetimeDetails(
$"{lifetime}: Call 1 to provider.GetRequiredService<ServiceLifetimeReporter>()");
Console.WriteLine("...");
logger = provider.GetRequiredService<ServiceLifetimeReporter>();
logger.ReportServiceLifetimeDetails(
$"{lifetime}: Call 2 to provider.GetRequiredService<ServiceLifetimeReporter>()");
Console.WriteLine();
}
Her services.Add{LIFETIME}<{SERVICE}>
uzantı yöntemi hizmetleri ekler (ve potansiyel olarak yapılandırılır). Uygulamaların bu kuralı izlemesini öneririz. Resmi bir Microsoft paketi yazmadığınız sürece uzantı yöntemlerini Microsoft.Extensions.DependencyInjection ad alanına yerleştirmeyin. Ad alanı içinde Microsoft.Extensions.DependencyInjection
tanımlanan uzantı yöntemleri:
- Ek bloklar gerektirmeden
using
IntelliSense'te görüntülenir. - Bu uzantı yöntemlerinin genellikle çağrıldığı veya
Startup
sınıflarındakiProgram
gerekliusing
deyimlerin sayısını azaltın.
Uygulama:
- Konak oluşturucu ayarlarıyla bir IHostBuilder örnek oluşturur.
- Hizmetleri yapılandırır ve bunlara karşılık gelen hizmet ömrüyle ekler.
- öğesini çağırır Build() ve bir örneğini IHostatar.
- çağrısı yaparak
ExemplifyScoping
öğesini geçirir IHost.Services.
Sonuç
Bu örnek uygulamada, çeşitli arabirimler ve buna karşılık gelen uygulamalar oluşturdunuz. Bu hizmetlerin her biri benzersiz olarak tanımlanır ve ile ServiceLifetimeeşleştirilir. Örnek uygulama, hizmet uygulamalarını bir arabirime kaydetmeyi ve arabirimleri yedeklemeden saf sınıfları kaydetmeyi gösterir. Örnek uygulama daha sonra oluşturucu parametreleri olarak tanımlanan bağımlılıkların çalışma zamanında nasıl çözüldüğünü gösterir.
Uygulamayı çalıştırdığınızda, aşağıdakine benzer bir çıkış görüntüler:
// Sample output:
// Lifetime 1: Call 1 to provider.GetRequiredService<ServiceLifetimeReporter>()
// IExampleTransientService: d08a27fa-87d2-4a06-98d7-2773af886125 (Always different)
// IExampleScopedService: 402c83c9-b4ed-4be1-b78c-86be1b1d908d (Changes only with lifetime)
// IExampleSingletonService: a61f1ff4-0b14-4508-bd41-21d852484a7b (Always the same)
// ...
// Lifetime 1: Call 2 to provider.GetRequiredService<ServiceLifetimeReporter>()
// IExampleTransientService: b43d68fb-2c7b-4a9b-8f02-fc507c164326 (Always different)
// IExampleScopedService: 402c83c9-b4ed-4be1-b78c-86be1b1d908d (Changes only with lifetime)
// IExampleSingletonService: a61f1ff4-0b14-4508-bd41-21d852484a7b (Always the same)
//
// Lifetime 2: Call 1 to provider.GetRequiredService<ServiceLifetimeReporter>()
// IExampleTransientService: f3856b59-ab3f-4bbd-876f-7bab0013d392 (Always different)
// IExampleScopedService: bba80089-1157-4041-936d-e96d81dd9d1c (Changes only with lifetime)
// IExampleSingletonService: a61f1ff4-0b14-4508-bd41-21d852484a7b (Always the same)
// ...
// Lifetime 2: Call 2 to provider.GetRequiredService<ServiceLifetimeReporter>()
// IExampleTransientService: a8015c6a-08cd-4799-9ec3-2f2af9cbbfd2 (Always different)
// IExampleScopedService: bba80089-1157-4041-936d-e96d81dd9d1c (Changes only with lifetime)
// IExampleSingletonService: a61f1ff4-0b14-4508-bd41-21d852484a7b (Always the same)
Uygulama çıkışında şunları görebilirsiniz:
- Transient hizmetler her zaman farklıdır, hizmetin her alımıyla yeni bir örnek oluşturulur.
- Scoped hizmetler yalnızca yeni bir kapsamla değişir, ancak kapsam içinde aynı örnektir.
- Singleton hizmetleri her zaman aynıdır, yeni bir örnek yalnızca bir kez oluşturulur.