ASP.NET Core Blazor bağımlılık ekleme
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Tarafından Rainer Stropek ve Mike Rousos
Bu makalede uygulamaların bileşenlere nasıl Blazor hizmet ekleyebileceğiniz açıklanmaktadır.
Bağımlılık ekleme (DI), merkezi bir konumda yapılandırılan hizmetlere erişmek için kullanılan bir tekniktir:
- Çerçeveye kayıtlı hizmetler doğrudan bileşenlere Razor eklenebilir.
- Blazor uygulamalar özel hizmetleri tanımlar ve kaydeder ve DI aracılığıyla uygulama genelinde kullanılabilir hale getirir.
Not
Bu konuyu okumadan önce ASP.NET Core'da bağımlılık ekleme konusunu okumanızı öneririz.
Varsayılan hizmetler
Aşağıdaki tabloda gösterilen hizmetler genellikle uygulamalarda kullanılır Blazor .
Hizmet | Yaşam süresi | Açıklama |
---|---|---|
HttpClient | Kapsamlı | URI tarafından tanımlanan bir kaynaktan HTTP istekleri göndermek ve HTTP yanıtları almak için yöntemler sağlar. İstemci tarafında, örneğinin bir örneği HttpClient dosyada Sunucu tarafı, HttpClient varsayılan olarak bir hizmet olarak yapılandırılmaz. Sunucu tarafı kodunda bir HttpClientsağlayın. Daha fazla bilgi için bkz . ASP.NET Core Blazor uygulamasından web API'sini çağırma. , HttpClient tekil olarak değil kapsamlı bir hizmet olarak kaydedilir. Daha fazla bilgi için Hizmet ömrü bölümüne bakın. |
IJSRuntime | İstemci tarafı: Singleton Sunucu tarafı: Kapsamlı Çerçeve, Blazor uygulamanın hizmet kapsayıcısında kaydeder IJSRuntime . |
JavaScript çağrılarının gönderildiği bir JavaScript çalışma zamanının örneğini temsil eder. Daha fazla bilgi için bkz. ASP.NET Core Blazor'da .NET yöntemlerinden JavaScript işlevlerini çağırma. Hizmeti sunucudaki tek bir hizmete eklemek istediğinizde aşağıdaki yaklaşımlardan birini uygulayın:
|
NavigationManager | İstemci tarafı: Singleton Sunucu tarafı: Kapsamlı Çerçeve, Blazor uygulamanın hizmet kapsayıcısında kaydeder NavigationManager . |
URI'lerle ve gezinti durumuyla çalışmaya yönelik yardımcılar içerir. Daha fazla bilgi için bkz . URI ve gezinti durumu yardımcıları. |
Çerçeve tarafından Blazor kaydedilen ek hizmetler, yapılandırma ve günlüğe kaydetme gibi özellikleri açıklamak Blazor için kullanıldıkları belgelerde açıklanmıştır.
Özel hizmet sağlayıcısı tabloda listelenen varsayılan hizmetleri otomatik olarak sağlamaz. Özel bir hizmet sağlayıcısı kullanıyorsanız ve tabloda gösterilen hizmetlerden herhangi birini gerektiriyorsanız, gerekli hizmetleri yeni hizmet sağlayıcısına ekleyin.
İstemci tarafı hizmetleri ekleme
Dosyadaki uygulamanın hizmet koleksiyonu Program
için hizmetleri yapılandırın. Aşağıdaki örnekte, ExampleDependency
uygulaması için IExampleDependency
kaydedilir:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.Services.AddSingleton<IExampleDependency, ExampleDependency>();
...
await builder.Build().RunAsync();
Konak oluşturulduktan sonra, tüm bileşenler işlenmeden önce kök DI kapsamından hizmetler kullanılabilir. Bu, içeriği işlemeden önce başlatma mantığını çalıştırmak için yararlı olabilir:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.Services.AddSingleton<WeatherService>();
...
var host = builder.Build();
var weatherService = host.Services.GetRequiredService<WeatherService>();
await weatherService.InitializeWeatherAsync();
await host.RunAsync();
Konak, uygulama için merkezi bir yapılandırma örneği sağlar. Yukarıdaki örnekte, hava durumu hizmetinin URL'si varsayılan yapılandırma kaynağından (örneğin, appsettings.json
) öğesine InitializeWeatherAsync
geçirilir:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.Services.AddSingleton<WeatherService>();
...
var host = builder.Build();
var weatherService = host.Services.GetRequiredService<WeatherService>();
await weatherService.InitializeWeatherAsync(
host.Configuration["WeatherServiceUrl"]);
await host.RunAsync();
Sunucu tarafı hizmetleri ekleme
Yeni bir uygulama oluşturduktan sonra dosyanın bir bölümünü Program
inceleyin:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder
değişkeni, hizmet tanımlayıcısı nesnelerinin listesi olan ile bir IServiceCollectionöğesini temsil ederWebApplicationBuilder. Hizmetler, hizmet koleksiyonuna hizmet tanımlayıcıları sağlanarak eklenir. Aşağıdaki örnekte, arabirimi ve somut uygulaması DataAccess
ile IDataAccess
kavramı gösterilmektedir:
builder.Services.AddSingleton<IDataAccess, DataAccess>();
Yeni bir uygulama oluşturduktan sonra içindeki yöntemini Startup.cs
inceleyinStartup.ConfigureServices
:
using Microsoft.Extensions.DependencyInjection;
...
public void ConfigureServices(IServiceCollection services)
{
...
}
yöntemineConfigureServices, hizmet tanımlayıcısı nesnelerinin listesi olan bir geçirilirIServiceCollection. Hizmetler, hizmet koleksiyonuna ConfigureServices
hizmet tanımlayıcıları sağlanarak yöntemine eklenir. Aşağıdaki örnekte, arabirimi ve somut uygulaması DataAccess
ile IDataAccess
kavramı gösterilmektedir:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDataAccess, DataAccess>();
}
Ortak hizmetleri kaydetme
Bir veya daha fazla yaygın hizmet için istemci ve sunucu tarafı gerekiyorsa, ortak hizmet kayıtlarını bir yöntem istemci tarafına yerleştirebilir ve her iki projede de hizmetleri kaydetmek için yöntemini çağırabilirsiniz.
İlk olarak, ortak hizmet kayıtlarını ayrı bir yönteme ekleyin. Örneğin, istemci tarafı bir ConfigureCommonServices
yöntem oluşturun:
public static void ConfigureCommonServices(IServiceCollection services)
{
services.Add...;
}
İstemci tarafı Program
dosyası için, ortak hizmetleri kaydetmek için çağrısında ConfigureCommonServices
bulunun:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
ConfigureCommonServices(builder.Services);
Sunucu tarafı Program
dosyasında, ortak hizmetleri kaydetmek için çağrısında ConfigureCommonServices
bulunun:
var builder = WebApplication.CreateBuilder(args);
...
Client.Program.ConfigureCommonServices(builder.Services);
Bu yaklaşımın bir örneği için bkz . ASP.NET Core Blazor WebAssembly ek güvenlik senaryoları.
Prerendering sırasında başarısız olan istemci tarafı hizmetleri
Bu bölüm yalnızca s içindeki Blazor Web AppWebAssembly bileşenleri için geçerlidir.
Blazor Web Apps normalde istemci tarafı WebAssembly bileşenlerini önceden oluşturur. Bir uygulama yalnızca projede .Client
kayıtlı gerekli bir hizmetle çalıştırılıyorsa, bir bileşen ön kayıt sırasında gerekli hizmeti kullanmayı denediğinde uygulamanın yürütülmesi aşağıdakine benzer bir çalışma zamanı hatasıyla sonuçlanır:
InvalidOperationException: '{ASSEMBLY}} türündeki {PROPERTY} için bir değer sağlanamaz. Client.Pages. {BILEŞEN ADı}'. '{SERVICE}' türünde kayıtlı hizmet yok.
Bu sorunu çözmek için aşağıdaki yaklaşımlardan birini kullanın:
- Bileşen hazırlama sırasında kullanılabilir hale getirmek için hizmeti ana projeye kaydedin.
- Bileşen için prerendering gerekli değilse, ASP.NET Core Blazor işleme modlarındaki yönergeleri izleyerek ön kayıt özelliğini devre dışı bırakın. Bu yaklaşımı benimserseniz, hizmeti ana projeye kaydetmeniz gerekmez.
Daha fazla bilgi için bkz . İstemci tarafı hizmetleri ön kayıt sırasında çözümlenememesi.
Hizmet ömrü
Hizmetler, aşağıdaki tabloda gösterilen yaşam süreleri ile yapılandırılabilir.
Yaşam süresi | Açıklama |
---|---|
Scoped | İstemci tarafı şu anda DI kapsamları kavramına sahip değildir. Sunucu tarafı geliştirme, http isteklerinde
Sunucu tarafı uygulamalarda kullanıcı durumunu koruma hakkında daha fazla bilgi için bkz . ASP.NET Çekirdek Blazor durum yönetimi. |
Singleton | DI, hizmetin tek bir örneğini oluşturur. Hizmet Singleton gerektiren tüm bileşenler hizmetin aynı örneğini alır. |
Transient | Bir bileşen hizmet kapsayıcısından bir Transient hizmet örneği aldığında hizmetin yeni bir örneğini alır. |
DI sistemi, ASP.NET Core'daki DI sistemini temel alır. Daha fazla bilgi için, bkz. ASP.NET Core'de bağımlılık ekleme.
Bileşende hizmet isteme
Hizmetleri bileşenlere eklemek için oluşturucu Blazor ekleme ve özellik eklemeyi destekler.
Oluşturucu ekleme
Hizmetler hizmet koleksiyonuna eklendikten sonra, oluşturucu ekleme ile bileşenlere bir veya daha fazla hizmet ekleyin. Aşağıdaki örnek hizmeti ekler NavigationManager
.
ConstructorInjection.razor
:
@page "/constructor-injection"
<button @onclick="HandleClick">
Take me to the Counter component
</button>
ConstructorInjection.razor.cs
:
using Microsoft.AspNetCore.Components;
public partial class ConstructorInjection(NavigationManager navigation)
{
private void HandleClick()
{
navigation.NavigateTo("/counter");
}
}
Özellik ekleme
Hizmetler hizmet koleksiyonuna eklendikten sonra, iki parametresi olan yönergesiyle @inject
Razor bileşenlere bir veya daha fazla hizmet ekleyin:
- Tür: Eklenen hizmetin türü.
- Özellik: Eklenen uygulama hizmetini alan özelliğin adı. özelliği el ile oluşturulmasını gerektirmez. Derleyici özelliği oluşturur.
Daha fazla bilgi için bkz . ASP.NET Core'da görünümlere bağımlılık ekleme.
Farklı hizmetler eklemek için birden çok @inject
deyim kullanın.
Aşağıdaki örnekte yönergesinin nasıl kullanılacağı gösterilmektedir @inject
. Uygulayan Services.NavigationManager
hizmet bileşenin özelliğine Navigation
eklenir. Kodda yalnızca soyutlamanın nasıl kullanıldığına NavigationManager
dikkat edin.
PropertyInjection.razor
:
@page "/property-injection"
@inject NavigationManager Navigation
<button @onclick="@(() => Navigation.NavigateTo("/counter"))">
Take me to the Counter component
</button>
Dahili olarak, oluşturulan özellik (Navigation
) özniteliğini [Inject]
kullanır. Genellikle bu öznitelik doğrudan kullanılmaz. Bileşenler için bir temel sınıf gerekiyorsa ve eklenen özellikler de temel sınıf için gerekliyse, özniteliğini el ile ekleyin:[Inject]
using Microsoft.AspNetCore.Components;
public class ComponentBase : IComponent
{
[Inject]
protected NavigationManager Navigation { get; set; } = default!;
...
}
Not
Eklenen hizmetlerin kullanılabilir olması beklendiğinden, null-forgiving işleci (default!
) ile varsayılan değişmez değer .NET 6 veya sonraki sürümlerde atanır. Daha fazla bilgi için bkz . Null atanabilir başvuru türleri (NTS) ve .NET derleyicisi null durum statik analizi.
Temel sınıftan türetilen bileşenlerde @inject
yönergesi gerekli değildir. InjectAttribute Temel sınıfın sayısı yeterlidir. Bileşen yalnızca yönergesini @inherits
gerektirir. Aşağıdaki örnekte, eklenen tüm hizmetleri CustomComponentBase
bileşeni tarafından Demo
kullanılabilir:
@page "/demo"
@inherits CustomComponentBase
Hizmetlerde DI kullanma
Karmaşık hizmetler ek hizmetler gerektirebilir. Aşağıdaki örnekte varsayılan DataAccess
hizmet gereklidir HttpClient . @inject
(veya [Inject]
özniteliği) hizmetlerde kullanılamaz. Bunun yerine oluşturucu ekleme kullanılmalıdır. Gerekli hizmetler, hizmetin oluşturucusunun parametreleri eklenerek eklenir. DI hizmeti oluşturduğunda, oluşturucuda gerektirdiği hizmetleri tanır ve uygun şekilde sağlar. Aşağıdaki örnekte, oluşturucu DI aracılığıyla bir HttpClient alır. HttpClient varsayılan bir hizmettir.
using System.Net.Http;
public class DataAccess : IDataAccess
{
public DataAccess(HttpClient http)
{
...
}
...
}
Oluşturucu ekleme, C# 12 (.NET 8) veya sonraki sürümlerde birincil oluşturucularla desteklenir:
using System.Net.Http;
public class DataAccess(HttpClient http) : IDataAccess
{
...
}
Oluşturucu ekleme önkoşulları:
- Bağımsız değişkenlerinin tümü DI tarafından yerine getirilebilen bir oluşturucu bulunmalıdır. Varsayılan değerleri belirtirlerse DI tarafından kapsanmayan ek parametrelere izin verilir.
- İlgili oluşturucu olmalıdır
public
. - Geçerli bir oluşturucu mevcut olmalıdır. Bir belirsizlik durumunda, DI bir özel durum oluşturur.
Anahtarlı hizmetleri bileşenlere ekleme
Blazor özniteliğini kullanarak anahtarlı hizmetler eklemeyi [Inject]
destekler. Anahtarlar, bağımlılık ekleme kullanılırken hizmetlerin kaydının ve tüketiminin kapsamını belirlemeye olanak sağlar. InjectAttribute.Key Hizmetin eklenecek anahtarını belirtmek için özelliğini kullanın:
[Inject(Key = "my-service")]
public IMyService MyService { get; set; }
DI kapsamını yönetmek için yardımcı program temel bileşen sınıfları
ASP.NET Core olmayanBlazor uygulamalarda kapsamı belirlenmiş ve geçici hizmetler genellikle geçerli istek kapsamındadır. İstek tamamlandıktan sonra, kapsamlı ve geçici hizmetler DI sistemi tarafından atılır.
Etkileşimli sunucu tarafı Blazor uygulamalarda DI kapsamı, devre süresi boyunca ( SignalR istemci ile sunucu arasındaki bağlantı) sürer ve bu da kapsamı belirlenmiş ve tek kullanımlık geçici hizmetlerin tek bir bileşenin ömründen çok daha uzun süre yaşamasına neden olabilir. Bu nedenle, hizmet ömrünün bileşenin ömrüyle eşleşmesini istiyorsanız, kapsamlı bir hizmeti doğrudan bir bileşene eklemeyin. Uygulamayan IDisposable bir bileşene eklenen geçici hizmetler, bileşen atıldığında çöp toplanır. Ancak, uygulanan IDisposable eklenen geçici hizmetler, devrenin ömrü boyunca DI kapsayıcısı tarafından korunur ve bu da bileşen atıldığında hizmet çöp toplamasını önler ve bellek sızıntısına neden olur. Türüne dayalı kapsamlı hizmetler için alternatif bir yaklaşım bu bölümün OwningComponentBase ilerleyen bölümlerinde açıklanmıştır ve tek kullanımlık geçici hizmetler hiç kullanılmamalıdır. Daha fazla bilgi için bkz . Geçici atılabilir öğeleri Blazor Server çözmek için tasarım (dotnet/aspnetcore
#26676).
Bir bağlantı hattı üzerinde çalışmayan istemci tarafı Blazor uygulamalarında bile, kapsamı belirlenmiş bir yaşam süresiyle kaydedilen hizmetler tekil olarak ele alınır, bu nedenle tipik ASP.NET Core uygulamalarında kapsamı belirlenmiş hizmetlerden daha uzun süre yaşarlar. İstemci tarafı atılabilir geçici hizmetler, tek kullanımlık hizmetlere başvurular tutan DI kapsayıcısı uygulamanın kullanım ömrü boyunca devam ettiğinden, hizmetlerin çöp toplamasını önlediğinden eklendikleri bileşenlerden daha uzun süre de yaşar. Uzun süreli tek kullanımlık geçici hizmetler sunucuda daha fazla endişe verici olsa da, istemci hizmeti kayıtları olarak da bu hizmetlerden kaçınılmalıdır. OwningComponentBase Tür kullanımı, hizmet ömrünü denetlemek için istemci tarafı kapsamlı hizmetler için de önerilir ve tek kullanımlık geçici hizmetler hiç kullanılmamalıdır.
Hizmet ömrünü sınırlayan bir yaklaşım, türün OwningComponentBase kullanılmasıdır. OwningComponentBase, bileşenin ComponentBaseömrüne karşılık gelen bir DI kapsamı oluşturan soyut bir türdür. Bu kapsamı kullanarak, bir bileşen kapsamlı bir yaşam süresine sahip hizmetler ekleyebilir ve bileşen kadar uzun süre yaşamalarını sağlayabilir. Bileşen yok edildiğinde, bileşenin kapsamlı hizmet sağlayıcısından gelen hizmetler de atılır. Bu, bir bileşen içinde yeniden kullanılan ancak bileşenler arasında paylaşılmayan hizmetler için yararlı olabilir.
Türün OwningComponentBase iki sürümü kullanılabilir ve sonraki iki bölümde açıklanmıştır:
OwningComponentBase
OwningComponentBase, türünde korumalı ScopedServices bir özelliğe sahip türün ComponentBase soyut, atılabilir bir alt öğesidirIServiceProvider. Sağlayıcı, bileşenin kullanım ömrü kapsamındaki hizmetleri çözümlemek için kullanılabilir.
veya [Inject]
özniteliği kullanılarak @inject
bileşene eklenen DI hizmetleri, bileşenin kapsamında oluşturulmaz. Bileşenin kapsamını kullanmak için, hizmetler veya GetServiceile kullanılarak ScopedServices GetRequiredService çözümlenmelidir. Sağlayıcı kullanılarak ScopedServices çözümlenen tüm hizmetlerin bağımlılıkları bileşenin kapsamında sağlanır.
Aşağıdaki örnekte, kapsamı belirlenmiş bir hizmeti doğrudan ekleme ile sunucuda kullanarak ScopedServices bir hizmeti çözümleme arasındaki fark gösterilmektedir. Bir zaman yolculuğu sınıfı için aşağıdaki arabirim ve uygulama, bir değeri tutmak için bir DT
DateTime özellik içerir. Uygulama, sınıfın TimeTravel
örneği oluşturulurken ayarlamak DT
için çağrısında DateTime.Now bulunur.
ITimeTravel.cs
:
public interface ITimeTravel
{
public DateTime DT { get; set; }
}
TimeTravel.cs
:
public class TimeTravel : ITimeTravel
{
public DateTime DT { get; set; } = DateTime.Now;
}
Hizmet, sunucu tarafı Program
dosyasında kapsamı belirlenmiş olarak kaydedilir. Sunucu tarafı, kapsamlı hizmetler, devrenin süresine eşit bir yaşam süresine sahiptir.
Program
dosyasında:
builder.Services.AddScoped<ITimeTravel, TimeTravel>();
Aşağıdaki TimeTravel
bileşeninde:
- Zaman yolculuğu hizmeti doğrudan olarak
TimeTravel1
eklenir@inject
. - Hizmet ayrıca ve GetRequiredService
TimeTravel2
ile ScopedServices ayrı olarak çözümlenir.
TimeTravel.razor
:
@page "/time-travel"
@inject ITimeTravel TimeTravel1
@inherits OwningComponentBase
<h1><code>OwningComponentBase</code> Example</h1>
<ul>
<li>TimeTravel1.DT: @TimeTravel1?.DT</li>
<li>TimeTravel2.DT: @TimeTravel2?.DT</li>
</ul>
@code {
private ITimeTravel TimeTravel2 { get; set; } = default!;
protected override void OnInitialized()
{
TimeTravel2 = ScopedServices.GetRequiredService<ITimeTravel>();
}
}
@page "/time-travel"
@inject ITimeTravel TimeTravel1
@inherits OwningComponentBase
<h1><code>OwningComponentBase</code> Example</h1>
<ul>
<li>TimeTravel1.DT: @TimeTravel1?.DT</li>
<li>TimeTravel2.DT: @TimeTravel2?.DT</li>
</ul>
@code {
private ITimeTravel TimeTravel2 { get; set; } = default!;
protected override void OnInitialized()
{
TimeTravel2 = ScopedServices.GetRequiredService<ITimeTravel>();
}
}
Başlangıçta bileşene TimeTravel
gitmek için, zaman yolculuğu hizmeti bileşen yüklendiğinde iki kez örneklenir ve TimeTravel1
TimeTravel2
aynı başlangıç değerine sahiptir:
TimeTravel1.DT: 8/31/2022 2:54:45 PM
TimeTravel2.DT: 8/31/2022 2:54:45 PM
Bileşenden TimeTravel
başka bir bileşene ve bileşene TimeTravel
geri dönerken:
TimeTravel1
, bileşen ilk yüklendiğinde oluşturulan hizmet örneğinin aynısı sağlanır, bu nedenle değeriDT
aynı kalır.TimeTravel2
içinde yeniITimeTravel
bir DT değeriyle yeni bir hizmet örneğiTimeTravel2
alır.
TimeTravel1.DT: 8/31/2022 2:54:45 PM
TimeTravel2.DT: 8/31/2022 2:54:48 PM
TimeTravel1
kullanıcının bağlantı hattına bağlıdır. Bu bağlantı hattı bozulmadan kalır ve temel bağlantı hattı kaldırılana kadar atılamaz. Örneğin, bağlantısı kesilmiş devre saklama süresi için bağlantı hattı kesilirse hizmet atılır.
Dosyadaki Program
kapsamlı hizmet kaydına ve kullanıcının bağlantı hattının uzun ömürlü olmasına rağmen, TimeTravel2
bileşen her başlatıldığında yeni ITimeTravel
bir hizmet örneği alır.
OwningComponentBase<TService>
OwningComponentBase<TService>türetilir OwningComponentBase ve kapsamı belirlenmiş DI sağlayıcısından bir örneğini T
döndüren bir özellik eklerService. Bu tür, bileşenin kapsamını kullanarak DI kapsayıcısından uygulamanın gerektirdiği tek bir birincil hizmet olduğunda örneği IServiceProvider kullanmadan kapsamlı hizmetlere erişmenin kullanışlı bir yoludur. ScopedServices Özelliği kullanılabilir, böylece uygulama gerekirse diğer türlerdeki hizmetleri alabilir.
@page "/users"
@attribute [Authorize]
@inherits OwningComponentBase<AppDbContext>
<h1>Users (@Service.Users.Count())</h1>
<ul>
@foreach (var user in Service.Users)
{
<li>@user.UserName</li>
}
</ul>
İstemci tarafı geçici atılabilirleri algılama
Kullanması OwningComponentBasegereken bir uygulamadaki tek kullanımlık geçici hizmetleri algılamak için istemci tarafı Blazor uygulamasına özel kod eklenebilir. Bu yaklaşım, gelecekte uygulamaya eklenen kodun kitaplıklar tarafından eklenen hizmetler de dahil olmak üzere bir veya daha fazla geçici atılabilir hizmet kullandığından endişe ediyorsanız kullanışlıdır. Örnek GitHub deposunda (nasıl indirilir) tanıtım kodu bulunurBlazor.
Örneğin .NET 6 veya sonraki sürümlerinde BlazorSample_WebAssembly
aşağıdakileri inceleyin:
DetectIncorrectUsagesOfTransientDisposables.cs
Services/TransientDisposableService.cs
- içinde
Program.cs
:- Uygulamanın
Services
ad alanı, dosyanın (using BlazorSample.Services;
) en üstünde sağlanır. DetectIncorrectUsageOfTransients
, 'den atandıktan hemen sonrabuilder
çağrılır WebAssemblyHostBuilder.CreateDefault.TransientDisposableService
kaydedilir (builder.Services.AddTransient<TransientDisposableService>();
).EnableTransientDisposableDetection
, uygulamanın (host.EnableTransientDisposableDetection();
) işlem hattındaki yerleşik ana bilgisayarda çağrılır.
- Uygulamanın
- Uygulama, özel durum oluşturmadan hizmeti kaydeder
TransientDisposableService
. Ancak, içindeTransientService.razor
hizmetini çözümlemeye çalışmak, çerçeve bir örneğiniTransientDisposableService
oluşturma girişiminde bulununca bir oluştururInvalidOperationException.
Sunucu tarafı geçici tek kullanımlıkları algılama
Kullanması OwningComponentBasegereken bir uygulamada sunucu tarafı atılabilir geçici hizmetleri algılamak için bir sunucu tarafı Blazor uygulamasına özel kod eklenebilir. Bu yaklaşım, gelecekte uygulamaya eklenen kodun kitaplıklar tarafından eklenen hizmetler de dahil olmak üzere bir veya daha fazla geçici atılabilir hizmet kullandığından endişe ediyorsanız kullanışlıdır. Örnek GitHub deposunda (nasıl indirilir) tanıtım kodu bulunurBlazor.
Örneğin .NET 8 veya sonraki sürümlerinde BlazorSample_BlazorWebApp
aşağıdakileri inceleyin:
Örneğin .NET 6 veya .NET 7 sürümlerinde BlazorSample_Server
aşağıdakileri inceleyin:
DetectIncorrectUsagesOfTransientDisposables.cs
Services/TransitiveTransientDisposableDependency.cs
:- içinde
Program.cs
:- Uygulamanın
Services
ad alanı, dosyanın (using BlazorSample.Services;
) en üstünde sağlanır. DetectIncorrectUsageOfTransients
, ana bilgisayar oluşturucusunun (builder.DetectIncorrectUsageOfTransients();
) üzerinde çağrılır.- Hizmet
TransientDependency
kayıtlıdır (builder.Services.AddTransient<TransientDependency>();
). TransitiveTransientDisposableDependency
( içinITransitiveTransientDisposableDependency
builder.Services.AddTransient<ITransitiveTransientDisposableDependency, TransitiveTransientDisposableDependency>();
kaydedilir.
- Uygulamanın
- Uygulama, özel durum oluşturmadan hizmeti kaydeder
TransientDependency
. Ancak, içindeTransientService.razor
hizmetini çözümlemeye çalışmak, çerçeve bir örneğiniTransientDependency
oluşturma girişiminde bulununca bir oluştururInvalidOperationException.
İşleyiciler için IHttpClientFactory
/HttpClient
geçici hizmet kayıtları
İşleyiciler için IHttpClientFactory/HttpClient geçici hizmet kayıtları önerilir. Uygulama işleyiciler içeriyorsa IHttpClientFactory/HttpClient ve kimlik doğrulaması için destek eklemek için öğesini IRemoteAuthenticationBuilder<TRemoteAuthenticationState,TAccount> kullanıyorsa, istemci tarafı kimlik doğrulaması için aşağıdaki geçici atılabilir öğeler de bulunur ve bu da beklenen ve yoksayılabilir:
Diğer örnekleri IHttpClientFactory/HttpClient de bulunur. Bu örnekler de yoksayılabilir.
Blazor Örnek GitHub deposundaki Blazor örnek uygulamalar (nasıl indirilir) geçici atılabilir öğeleri algılama kodunu gösterir. Ancak örnek uygulamalar işleyiciler içerdiğinden IHttpClientFactory/HttpClient kod devre dışı bırakılır.
Tanıtım kodunu etkinleştirmek ve çalışmasına tanık olmak için:
içinde
Program.cs
geçici tek kullanımlık satırların açıklamasını kaldırın.Bileşenin uygulamanın gezinti kenar çubuğunda görüntülenmesini engelleyen
TransientService
koşullu denetimiNavLink.razor
kaldırın:- else if (name != "TransientService") + else
Örnek uygulamayı çalıştırın ve konumundaki
/transient-service
bileşeneTransientService
gidin.
DI'den Entity Framework Core (EF Core) DbContext kullanımı
Daha fazla bilgi için bkz. Entity Framework Core (EF Core) ile ASP.NET CoreBlazor.
Farklı bir DI kapsamından sunucu tarafı Blazor hizmetlerine erişme
Devre etkinliği işleyicileri, kullanılarak oluşturulan kapsamlar gibi diğer bağımlılık eklemeBlazor (DI) kapsamlarından kapsamı belirlenmiş Blazor hizmetlere erişmek için bir yaklaşım sağlar.IHttpClientFactory
.NET 8'de ASP.NET Core yayımlanmadan önce, özel bir temel bileşen türü kullanılarak gereken diğer bağımlılık ekleme kapsamlarından devre kapsamlı hizmetlere erişilir. Bağlantı hattı etkinlik işleyicilerinde, aşağıdaki örnekte gösterildiği gibi özel bir temel bileşen türü gerekli değildir:
public class CircuitServicesAccessor
{
static readonly AsyncLocal<IServiceProvider> blazorServices = new();
public IServiceProvider? Services
{
get => blazorServices.Value;
set => blazorServices.Value = value;
}
}
public class ServicesAccessorCircuitHandler(
IServiceProvider services, CircuitServicesAccessor servicesAccessor)
: CircuitHandler
{
public override Func<CircuitInboundActivityContext, Task> CreateInboundActivityHandler(
Func<CircuitInboundActivityContext, Task> next) =>
async context =>
{
servicesAccessor.Services = services;
await next(context);
servicesAccessor.Services = null;
};
}
public static class CircuitServicesServiceCollectionExtensions
{
public static IServiceCollection AddCircuitServicesAccessor(
this IServiceCollection services)
{
services.AddScoped<CircuitServicesAccessor>();
services.AddScoped<CircuitHandler, ServicesAccessorCircuitHandler>();
return services;
}
}
Gereken yere ekleyerek devre kapsamlı hizmetlere CircuitServicesAccessor
erişin.
kullanarak bir kurulumdan 'a nasıl erişildiğini AuthenticationStateProvider gösteren bir örnek için bkz. Sunucu tarafı ASP.NET Çekirdek Blazor ek güvenlik senaryoları.DelegatingHandler IHttpClientFactory
Bir bileşenin farklı bir Razor DI kapsamında kod yürüten zaman uyumsuz yöntemleri çağıracağı zamanlar olabilir. Doğru yaklaşım olmadan, bu DI kapsamlarının ve Microsoft.AspNetCore.Components.Server.ProtectedBrowserStoragegibi IJSRuntime hizmetlerine erişimi Blazoryoktur.
Örneğin, HttpClient kullanılarak IHttpClientFactory oluşturulan örneklerin kendi DI hizmet kapsamı vardır. Sonuç olarak, HttpMessageHandler üzerinde HttpClient yapılandırılan örnekler hizmetleri doğrudan eklemez Blazor .
Geçerli zaman uyumsuz bağlamın depolandığı BlazorIServiceProvider öğesini AsyncLocal
tanımlayan bir sınıf BlazorServiceAccessor
oluşturun. Bir BlazorServiceAccessor
örnek, hizmetlere erişmek Blazor için farklı bir DI hizmet kapsamından edinilebilir.
BlazorServiceAccessor.cs
:
internal sealed class BlazorServiceAccessor
{
private static readonly AsyncLocal<BlazorServiceHolder> s_currentServiceHolder = new();
public IServiceProvider? Services
{
get => s_currentServiceHolder.Value?.Services;
set
{
if (s_currentServiceHolder.Value is { } holder)
{
// Clear the current IServiceProvider trapped in the AsyncLocal.
holder.Services = null;
}
if (value is not null)
{
// Use object indirection to hold the IServiceProvider in an AsyncLocal
// so it can be cleared in all ExecutionContexts when it's cleared.
s_currentServiceHolder.Value = new() { Services = value };
}
}
}
private sealed class BlazorServiceHolder
{
public IServiceProvider? Services { get; set; }
}
}
Bir async
bileşen yöntemi çağrıldığında değerini BlazorServiceAccessor.Services
otomatik olarak ayarlamak için, bileşen koduna Razor üç birincil zaman uyumsuz giriş noktasını yeniden uygulayan özel bir temel bileşen oluşturun:
Aşağıdaki sınıf temel bileşen için uygulamayı gösterir.
CustomComponentBase.cs
:
using Microsoft.AspNetCore.Components;
public class CustomComponentBase : ComponentBase, IHandleEvent, IHandleAfterRender
{
private bool hasCalledOnAfterRender;
[Inject]
private IServiceProvider Services { get; set; } = default!;
[Inject]
private BlazorServiceAccessor BlazorServiceAccessor { get; set; } = default!;
public override Task SetParametersAsync(ParameterView parameters)
=> InvokeWithBlazorServiceContext(() => base.SetParametersAsync(parameters));
Task IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, object? arg)
=> InvokeWithBlazorServiceContext(() =>
{
var task = callback.InvokeAsync(arg);
var shouldAwaitTask = task.Status != TaskStatus.RanToCompletion &&
task.Status != TaskStatus.Canceled;
StateHasChanged();
return shouldAwaitTask ?
CallStateHasChangedOnAsyncCompletion(task) :
Task.CompletedTask;
});
Task IHandleAfterRender.OnAfterRenderAsync()
=> InvokeWithBlazorServiceContext(() =>
{
var firstRender = !hasCalledOnAfterRender;
hasCalledOnAfterRender |= true;
OnAfterRender(firstRender);
return OnAfterRenderAsync(firstRender);
});
private async Task CallStateHasChangedOnAsyncCompletion(Task task)
{
try
{
await task;
}
catch
{
if (task.IsCanceled)
{
return;
}
throw;
}
StateHasChanged();
}
private async Task InvokeWithBlazorServiceContext(Func<Task> func)
{
try
{
BlazorServiceAccessor.Services = Services;
await func();
}
finally
{
BlazorServiceAccessor.Services = null;
}
}
}
Otomatik olarak genişleten CustomComponentBase
tüm bileşenler geçerli Blazor DI kapsamında olarak ayarlanmıştırIServiceProvider.BlazorServiceAccessor.Services
Son olarak, Program
dosyasına kapsamlı bir hizmet olarak öğesini ekleyin BlazorServiceAccessor
:
builder.Services.AddScoped<BlazorServiceAccessor>();
Son olarak, içinde Startup.ConfigureServices
Startup.cs
öğesini kapsamlı bir hizmet olarak ekleyin BlazorServiceAccessor
:
services.AddScoped<BlazorServiceAccessor>();
Ek kaynaklar
ASP.NET Core