Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, Windows Uygulama SDK'sı ile oluşturulan WinUI 3 masaüstü uygulamalarına kanıtlanmış mimari desenlerinin nasıl uygulanacağı gösterilmektedir. Kurumsal iş kolu (LOB) senaryoları için bağımlılık ekleme, yapılandırma ve yapı kodu ayarlamayı öğreneceksiniz.
Prerequisites
- Windows Uygulama SDK'sı 1.5 veya üzeri
- .NET 8 veya üzeri
- .NET masaüstü geliştirme ve Windowsuygulama geliştirme iş yükleriyle Visual Studio 2022 sürüm 17.10 veya üzeri
Bağımlılık enjeksiyonu
WinUI 3 masaüstü uygulamaları, ASP.NET Core gibi yerleşik bağımlılık ekleme (DI) kapsayıcısı içermez, ancak aynı Microsoft.Extensions.DependencyInjection NuGet paketini kullanarak bir kapsayıcı ekleyebilirsiniz. DI, kodunuzu test edilebilir, gevşek bağlı ve bakımı daha kolay hale getirir.
DI kapsayıcısını ayarlayın
NuGet paketini yükleyin:
dotnet add package Microsoft.Extensions.DependencyInjection
dotnet add package Microsoft.Extensions.Hosting
App.xaml.cs içinde ana bilgisayarı ve hizmetleri yapılandırın:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.UI.Xaml;
public partial class App : Application
{
public IHost Host { get; }
public static T GetService<T>() where T : class
{
if ((App.Current as App)!.Host.Services.GetService(typeof(T)) is not T service)
{
throw new ArgumentException(
$"{typeof(T)} needs to be registered in ConfigureServices.");
}
return service;
}
public App()
{
InitializeComponent();
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
.UseContentRoot(AppContext.BaseDirectory)
.ConfigureServices((context, services) =>
{
// Services
services.AddSingleton<INavigationService, NavigationService>();
services.AddSingleton<IDataService, DataService>();
services.AddTransient<IDialogService, DialogService>();
// ViewModels
services.AddTransient<MainViewModel>();
services.AddTransient<SettingsViewModel>();
// Views
services.AddTransient<MainPage>();
services.AddTransient<SettingsPage>();
})
.Build();
}
}
Note
Bir hizmeti kaydetmeyi unutursanız, yukarıdaki GetService<T>() yardımcı işlevi, çalışma zamanında eksik tür adıyla birlikte bir ArgumentException fırlatır. Uygulamayı çalıştırın ve geliştirme sırasında tüm kayıtların doğru olduğunu doğrulamak için her sayfaya gidin.
Bağımlılıkları ViewModel'lere ekleme
Kapsayıcı yapılandırıldığında, ViewModel'lerinize bağımlılıklar kurucu enjeksiyonu aracılığıyla sağlanır:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
private readonly IDataService _dataService;
private readonly INavigationService _navigationService;
public MainViewModel(IDataService dataService, INavigationService navigationService)
{
_dataService = dataService;
_navigationService = navigationService;
}
[ObservableProperty]
private string _statusMessage = string.Empty;
[RelayCommand]
private async Task LoadDataAsync()
{
StatusMessage = "Loading...";
var items = await _dataService.GetItemsAsync();
StatusMessage = $"Loaded {items.Count} items";
}
}
Hizmet ömrü
Hizmetleri kaydederken uygun ömrü seçin:
| Yaşam süresi | Method | Aşağıdakiler için kullanın: |
|---|---|---|
| Singleton | AddSingleton<T>() |
Gezinti, uygulama genelinde durum, önbellekler |
| Kapsamlı | AddScoped<T>() |
Pencereye özgü veya iletişim kutusuna özgü bağlamlar |
| Geçici | AddTransient<T>() |
ViewModels, durum bilgisi olmayan hizmetler |
Tip
Her gezintinin yeni bir örnek oluşturması için ViewModels'i Geçici olarak kaydedin. Uygulama genelinde durum tutan hizmetleri Singleton olarak kaydedin.
Yapılandırma yönetimi
Masaüstü uygulamalarında uygulama ayarlarını yönetmek için ASP.NET Core’da kullanılan aynı deseni, Microsoft.Extensions.Configuration kullanın.
Yapılandırma desteği ekleme
Gerekli paketleri yükleyin:
dotnet add package Microsoft.Extensions.Configuration
dotnet add package Microsoft.Extensions.Configuration.Json
dotnet add package Microsoft.Extensions.Options
Proje kökünde bir appsettings.json dosya oluşturun. Çözüm Gezgini’da dosyaya sağ tıklayın, Özellikler’i seçin ve Çıkış Dizinine Kopyala seçeneğini Daha yeniyse kopyala olarak ayarlayın. Alternatif olarak, .csproj içindeki dosya girdisine <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> ekleyin.
{
"AppSettings": {
"ApiBaseUrl": "https://api.contoso.com/v2",
"MaxRetryCount": 3,
"EnableTelemetry": true
},
"Logging": {
"LogLevel": "Information"
}
}
DI kurulumunuzda yapılandırmayı bağlayın:
.ConfigureServices((context, services) =>
{
// Bind settings to a strongly-typed class
services.Configure<AppSettings>(
context.Configuration.GetSection("AppSettings"));
// Inject IOptions<AppSettings> into services
services.AddSingleton<IApiClient, ApiClient>();
})
Hizmetlerde yapılandırmayı kullanma
using Microsoft.Extensions.Options;
public class ApiClient : IApiClient
{
private readonly AppSettings _settings;
private readonly HttpClient _httpClient;
public ApiClient(IOptions<AppSettings> options)
{
_settings = options.Value;
_httpClient = new HttpClient
{
BaseAddress = new Uri(_settings.ApiBaseUrl)
};
}
}
Kullanıcı ayarları kalıcılığı
Uygulama güncellemelerinden sonra da korunan kullanıcıya özgü ayarlar için, Windows.Storage.ApplicationData (paketlenmiş uygulamalar) veya yerel bir JSON dosyası (paketlenmemiş uygulamalar) kullanın:
public class UserSettingsService : IUserSettingsService
{
private readonly string _settingsPath;
public UserSettingsService()
{
var localAppData = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData);
_settingsPath = Path.Combine(localAppData, "Contoso", "MyApp", "settings.json");
}
public async Task SaveAsync<T>(string key, T value)
{
var settings = await LoadAllAsync();
settings[key] = JsonSerializer.Serialize(value);
Directory.CreateDirectory(Path.GetDirectoryName(_settingsPath)!);
await File.WriteAllTextAsync(
_settingsPath, JsonSerializer.Serialize(settings));
}
}
Note
Paketlenmiş uygulamalar (MSIX), basit anahtar-değer çiftleri için kullanılabilir ApplicationData.Current.LocalSettings . Paketlenmemiş uygulamaların kendi depolama konumlarını yönetmesi gerekir.
Özellik bayrakları
Aşamalı dağıtım ve A/B testlerini yeniden dağıtmadan etkinleştirmek için özellik bayrakları uygulayın.
Yapılandırmalı yerel özellik bayrakları
public interface IFeatureFlagService
{
bool IsEnabled(string featureName);
}
public class FeatureFlagService : IFeatureFlagService
{
private readonly Dictionary<string, bool> _flags;
public FeatureFlagService(IConfiguration configuration)
{
_flags = configuration.GetSection("FeatureFlags")
.Get<Dictionary<string, bool>>() ?? new();
}
public bool IsEnabled(string featureName) =>
_flags.TryGetValue(featureName, out var enabled) && enabled;
}
Azure Uygulama Yapılandırması tümleştirmesi
Bulut tarafından yönetilen özellik bayrakları için Azure Uygulama Yapılandırması kullanın:
dotnet add package Microsoft.Extensions.Configuration.AzureAppConfiguration
dotnet add package Microsoft.FeatureManagement
using Azure.Identity;
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((context, config) =>
{
config.AddAzureAppConfiguration(options =>
{
options.Connect(
new Uri("https://<your-store>.azconfig.io"),
new DefaultAzureCredential())
.UseFeatureFlags(flagOptions =>
{
flagOptions.CacheExpirationInterval = TimeSpan.FromMinutes(5);
});
});
})
.ConfigureServices((context, services) =>
{
services.AddFeatureManagement(context.Configuration);
})
.Build();
Note
Yerel geliştirme için, DefaultAzureCredential yerine bir bağlantı dizesi kullanabilirsiniz. bağlantı dizesi bir ortam değişkeninde veya Windows Kimlik Bilgileri Yöneticisi'nde depolayın; hiçbir zaman kaynak denetiminde yer almaz:
options.Connect(Environment.GetEnvironmentVariable("APP_CONFIG_CONNECTION_STRING"))
Tip
Paket düzeyinde Mağaza tabanlı aşamalı dağıtım için bkz. Aşamalı paket dağıtımı.
Kurumsal ve LOB kalıpları
İş kolu uygulamalarının kimlik, veri koruma ve cihaz yönetimiyle ilgili ek gereksinimleri vardır.
Kimlik ve koşullu erişim
Kurumsal kimlik doğrulaması için MSAL (Microsoft Authentication Library) kullanın:
services.AddSingleton<IAuthService>(sp =>
{
var app = PublicClientApplicationBuilder
.Create("your-client-id")
.WithAuthority(AzureCloudInstance.AzurePublic, "your-tenant-id")
.WithRedirectUri("http://localhost")
.Build();
return new AuthService(app);
});
Important
Yeniden yönlendirme URI'si http://localhost geliştirme için uygundur. Üretim masaüstü uygulamaları için bunun yerine, kullanıcının Windows hesabıyla SSO ve daha güçlü belirteç koruması sağlayan Windows aracısını (WAM) kullanın.
Intune aracılığıyla dağıtılan kurumsal uygulamalar, şunları gerektiren koşullu erişim ilkelerini zorunlu kılabilir:
- Cihaz uyumluluğu (şifreleme, PIN, işletim sistemi sürümü)
- Çok faktörlü kimlik doğrulaması
- Ağ konumu kısıtlamaları
Çevrimdışı veriler ve önbelleğe alma
Masaüstü LOB uygulamalarının sık sık çevrimdışı çalışması gerekir. Yerel önbelleğe alma ile bir depo deseni uygulayın:
public class CachedRepository<T> : IRepository<T> where T : class, IEntity
{
private readonly IApiClient _apiClient;
private readonly ILocalDatabase _localDb;
public async Task<IReadOnlyList<T>> GetAllAsync(bool forceRefresh = false)
{
if (!forceRefresh)
{
var cached = await _localDb.GetAllAsync<T>();
if (cached.Any())
return cached;
}
try
{
var items = await _apiClient.GetAsync<List<T>>();
await _localDb.UpsertAllAsync(items);
return items;
}
catch (HttpRequestException)
{
// Offline fallback
return await _localDb.GetAllAsync<T>();
}
}
}
Veri koruma
Hassas yerel verileri şifrelemek için (paketlenmiş uygulamalar) veya .NET Windows.Security.Cryptography.DataProtection kullanın DataProtectionProvider .
Gerekli paketi yükleyin:
dotnet add package Microsoft.AspNetCore.DataProtection.Extensions
Ardından DI kapsayıcınıza veri korumasını kaydedin:
using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.SetApplicationName("Contoso.LOBApp")
.ProtectKeysWithDpapi();
Katmanlı mimari
Bağımlılıkların tek bir yönde akmasını sağlamak için WinUI 3 uygulamanızı katmanlar halinde yapılandırma:
┌─────────────────────────────┐
│ Views (XAML + code-behind)│ ← UI layer, no business logic
├─────────────────────────────┤
│ ViewModels (MVVM Toolkit) │ ← Presentation logic, commands
├─────────────────────────────┤
│ Services / Use Cases │ ← Business rules, orchestration
├─────────────────────────────┤
│ Repositories / Data │ ← Data access, API clients, caching
└─────────────────────────────┘
Kurallar:
- Her katman yalnızca doğrudan altındaki katmana bağlıdır.
- ViewModel'ler hiçbir zaman kullanıcı arabirimi türlerine (
Page,Window,ContentDialog) başvurmaz. - Hizmetler arabirimleri tanımlar; uygulamaları veri katmanında bulunur.
- Di kapsayıcısında tüm katmanlar arası bağımlılıkları kaydedin.
Geriye dönük uyumluluk ve sürüm oluşturma
Uygulamanızın yeni sürümlerini yayımladığınızda şunları göz önünde bulundurun:
- Veri geçişi: Yerel veritabanı şemanızı sürümüne geçirin. Önceki herhangi bir şemadan geçerli şemaya yükseltmek için başlangıçta geçiş çalıştırıcısı kullanın.
- Ayarlar geçişi: Bir şema sürümünü ayarlar dosyanızda depolayın. Yükte, eski biçimlerden yeni biçimlere dönüşümler uygulayın.
- Yan yana yüklemeler: MSIX varsayılan olarak bir paketi yerinde yükselter. Birden çok ana sürümü yan yana çalıştırmak için, tasarım zamanında her sürüme ayrı bir paket ailesi adı atayın.
public class DatabaseMigrator
{
public async Task MigrateAsync(SqliteConnection db)
{
var currentVersion = await GetSchemaVersionAsync(db);
if (currentVersion < 2)
await ApplyMigration_v2(db);
if (currentVersion < 3)
await ApplyMigration_v3(db);
await SetSchemaVersionAsync(db, LatestVersion);
}
}
Kurulumunuzu doğrulama
Uygulamayı çalıştırın ve hizmetlerin doğru çözümlendiğini doğrulamak için her sayfaya gidin. Bir hizmet kayıtlı değilse, çalışma zamanında eksik tür adını içeren bir InvalidOperationException görürsünüz. Ayrıca şunları onaylayın:
- Yapılandırma değerleri
appsettings.jsonüzerinden yüklenir (hata ayıklayıcıda bağlı bir özelliği kontrol edin). - Özellik bayrakları beklendiği gibi çalışır (bir bayrağı açıp kapatın ve yeniden başlatın).
- Çevrimdışı önbelleğe alma, ağ kullanılamadığında verileri döndürür.
İlgili içerik
Windows developer