C#依赖项注入有重复的单例
我正在开发一个Xamarin.Forms应用程序,由于某些原因,其中有多次创建的单例。然而,这种情况并非每次都发生,而且似乎是随机发生的。我的依赖项注入设置发生在App.xaml.cs中C#依赖项注入有重复的单例,c#,xamarin,xamarin.forms,dependency-injection,singleton,C#,Xamarin,Xamarin.forms,Dependency Injection,Singleton,我正在开发一个Xamarin.Forms应用程序,由于某些原因,其中有多次创建的单例。然而,这种情况并非每次都发生,而且似乎是随机发生的。我的依赖项注入设置发生在App.xaml.cs中 using System; using Microsoft.AppCenter; using Microsoft.AppCenter.Analytics; using Microsoft.AppCenter.Crashes; using Microsoft.Extensions.DependencyInject
using System;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Microsoft.Extensions.DependencyInjection;
using Peripass.Mobile.Framework;
using Peripass.Mobile.Framework.DependencyInterfaces;
using Peripass.YardAssetManagementApp.Data;
using Peripass.YardAssetManagementApp.Data.FileSystem;
using Peripass.YardAssetManagementApp.Data.LocalDataServices;
using Peripass.YardAssetManagementApp.Data.Queues;
using Peripass.YardAssetManagementApp.Data.RemoteDataServices;
using Peripass.YardAssetManagementApp.Data.Syncing;
using Peripass.YardAssetManagementApp.Data.Syncing.QueueItemSyncActions;
using Peripass.YardAssetManagementApp.Device;
using Peripass.YardAssetManagementApp.MVVM;
using Peripass.YardAssetManagementApp.MVVM.Pages;
using Peripass.YardAssetManagementApp.PushNotifications;
using Peripass.YardAssetManagementApp.Services;
using Peripass.YardAssetManagementApp.StepsWizard;
using Peripass.YardAssetManagementApp.UI.Views;
using Peripass.YardAssetManagementApp.UserAuthentication;
using Peripass.YardAssetManagementApp.ViewModels;
using Xamarin.Forms;
using Application = Xamarin.Forms.Application;
namespace Peripass.YardAssetManagementApp {
public partial class App : Application, IApp {
private string _startedByAndroidNotificationMessage;
public App() {
ConfigureServices();
InitializeComponent();
AppCenter.Start($"android={Configuration.Configuration.ApplicationInsightsKeyAndroid};", typeof(Analytics), typeof(Crashes));
MainPage = ServiceProvider.GetRequiredService<MainPage>();
}
public static IServiceCollection Services { get; } = new ServiceCollection();
public IServiceProvider ServiceProvider { get; set; }
private void ConfigureServices() {
Services.AddSingleton<ILifecycleHooksService, LifecycleHooksService>();
Services.AddTransient<INetworkInformationProvider, NetworkInformationProvider>();
RegisterLocalDataServices();
RegisterRemoteDataServices();
RegisterSyncLogic();
RegisterServices();
RegisterViews();
Services.AddSingleton<IUserManager, UserManager>();
Services.AddSingleton<HttpClientProvider>();
Services.AddSingleton<ILogger, Logger>();
Services.AddSingleton<INavigationService, NavigationService>();
Services.AddSingleton<StepsWizardManager>();
Services.AddSingleton<MainPage>();
Services.AddSingleton(DependencyService.Get<ILocalFileSystem>());
Services.AddSingleton<IRestServiceHelper, RestServiceHelper>();
Services.AddSingleton<IPushNotificationsService, PushNotificationsService>();
ServiceProvider = Services.BuildServiceProvider();
}
public void RegisterServices() {
Services.AddTransient<ITaskService, TaskService>();
Services.AddTransient<ILocationService, LocationService>();
Services.AddTransient<ILocalizationService, LocalizationService>();
Services.AddTransient<IDiagnosticsService, DiagnosticsService>();
}
public void RegisterLocalDataServices() {
Services.AddSingleton<ILocalTaskDataService, LocalTaskDataService>();
Services.AddSingleton<ILocalLocationDataService, LocalLocationDataService>();
Services.AddSingleton<ILocalUserDataService, LocalUserDataService>();
Services.AddSingleton<ILocalPushNotificationDataService, LocalPushNotificationDataService>();
Services.AddSingleton<ILocalPictureDataService, LocalPictureDataService>();
Services.AddSingleton<ISafeFileSystem, SafeFileSystem>();
Services.AddSingleton<ILocalLocalizationDataService, LocalLocalizationDataService>();
}
public void RegisterRemoteDataServices() {
Services.AddSingleton<IRemoteTaskDataService, RemoteTaskDataService>();
Services.AddSingleton<IRemoteLocationDataService, RemoteLocationDataService>();
Services.AddSingleton<IRemoteUserDataService, RemoteUserDataService>();
Services.AddSingleton<IRemoteFileDataService, RemoteFileDataService>();
Services.AddSingleton<IRemoteLocalizationDataService, RemoteLocalizationDataService>();
}
public void RegisterSyncLogic() {
Services.AddSingleton<IToMobileTasksSyncer, ToMobileTasksSyncer>();
Services.AddSingleton<IQueue, IncomingHighPriorityQueue>();
Services.AddSingleton<IQueue, IncomingLowPriorityQueue>();
Services.AddSingleton<IQueue, OutgoingHighPriorityQueue>();
Services.AddSingleton<IQueue, OutgoingLowPriorityQueue>();
Services.AddSingleton<IQueue, PictureSyncLowPriorityQueue>();
Services.AddSingleton<IQueue, PictureSyncHighPriorityQueue>();
Services.AddSingleton<IQueueOrchestrator, IncomingQueueOrchestrator>();
Services.AddSingleton<IQueueOrchestrator, OutgoingQueueOrchestrator>();
Services.AddSingleton<IQueueOrchestrator, PictureQueueOrchestrator>();
Services.AddSingleton<IQueueProcessor, IncomingQueueProcessor>();
Services.AddSingleton<IQueueProcessor, OutgoingQueueProcessor>();
Services.AddSingleton<IQueueProcessor, PictureQueueProcessor>();
Services.AddSingleton<IQueueItemSyncAction, FetchTaskDetailSyncAction>();
Services.AddSingleton<IQueueItemSyncAction, OutgoingStepValueUpdateSyncAction>();
Services.AddSingleton<IQueueItemSyncAction, OutgoingTaskStatusChangedSyncAction>();
Services.AddSingleton<IQueueItemSyncAction, SyncPictureAction>();
Services.AddSingleton<IFileIntegrityHelper, FileIntegrityHelper>();
}
public void RegisterViews() {
Services.AddTransient<LoginViewContent>();
Services.AddSingleton<LoginViewModel>();
Services.AddTransient<UserInfoViewContent>();
Services.AddSingleton<UserInfoViewModel>();
Services.AddTransient<MainTaskListViewContent>();
Services.AddSingleton<MainTaskListViewModel>();
Services.AddTransient<TaskDetailViewContent>();
Services.AddSingleton<TaskDetailViewModel>();
Services.AddTransient<IntegerFieldTaskStepViewContent>();
Services.AddSingleton<IntegerFieldTaskStepViewModel>();
Services.AddTransient<TextAreaTaskStepViewContent>();
Services.AddSingleton<TextAreaTaskStepViewModel>();
Services.AddTransient<DropDownTaskStepViewContent>();
Services.AddSingleton<DropDownTaskStepViewModel>();
Services.AddTransient<MoveToLocationSummaryViewContent>();
Services.AddSingleton<MoveToLocationSummaryViewModel>();
Services.AddTransient<TakePictureStepViewContent>();
Services.AddSingleton<TakePictureStepViewModel>();
Services.AddTransient<MoveToLocationStepViewContent>();
Services.AddSingleton<MoveToLocationStepViewModel>();
Services.AddTransient<TaskCompletedViewContent>();
Services.AddSingleton<TaskCompletedViewModel>();
Services.AddTransient<LoggedOutViewContent>();
Services.AddSingleton<LoggedOutViewModel>();
Services.AddTransient<TextFieldTaskStepViewContent>();
Services.AddSingleton<TextFieldTaskStepViewModel>();
Services.AddTransient<DecimalFieldTaskStepViewContent>();
Services.AddSingleton<DecimalFieldTaskStepViewModel>();
Services.AddTransient<GenericExceptionPageViewContent>();
Services.AddSingleton<GenericExceptionPageViewModel>();
Services.AddTransient<CleanupBeforeLogoutPageViewContent>();
Services.AddSingleton<CleanupBeforeLogoutPageViewModel>();
Services.AddTransient<SelectLanguageViewContent>();
Services.AddSingleton<SelectLanguageViewModel>();
}
protected override async void OnStart() {
await ServiceProvider.GetRequiredService<ILifecycleHooksService>().OnStart();
}
protected override void OnSleep() { }
protected override async void OnResume() {
await ServiceProvider.GetRequiredService<ILifecycleHooksService>().OnResume();
}
public void StartedByTapOnAndroidNotification(string message) {
_startedByAndroidNotificationMessage = message;
}
}
}
使用系统;
使用Microsoft.AppCenter;
使用Microsoft.AppCenter.Analytics;
使用Microsoft.AppCenter.0崩溃;
使用Microsoft.Extensions.DependencyInjection;
使用Peripass.Mobile.Framework;
使用Peripass.Mobile.Framework.dependency接口;
使用Peripass.YardAssetManagementApp.Data;
使用Peripass.YardAssetManagementApp.Data.FileSystem;
使用Peripass.YardAssetManagementApp.Data.LocalDataServices;
使用Peripass.YardAssetManagementApp.Data.Queues;
使用Peripass.YardAssetManagementApp.Data.RemoteDataServices;
使用Peripass.YardAssetManagementApp.Data.Syncing;
使用Peripass.YardAssetManagementApp.Data.Syncing.QueueItemSyncActions;
使用Peripass.YardAssetManagementApp.Device;
使用Peripass.YardAssetManagementApp.MVVM;
使用Peripass.YardAssetManagementApp.MVVM.Pages;
使用Peripass.YardAssetManagementApp.PushNotifications;
使用Peripass.YardAssetManagementApp.Services;
使用Peripass.YardAssetManagementApp.StepsWizard;
使用Peripass.YardAssetManagementApp.UI.Views;
使用Peripass.YardAssetManagementApp.UserAuthentication;
使用Peripass.YardAssetManagementApp.ViewModels;
使用Xamarin.Forms;
使用Application=Xamarin.Forms.Application;
命名空间Peripass.YardAssetManagementApp{
公共部分类应用程序:应用程序,IApp{
由AndroidNotificationMessage启动的私有字符串;
公共应用程序(){
配置服务();
初始化组件();
AppCenter.Start($“android={Configuration.Configuration.ApplicationInsightsKeyAndroid};”,typeof(分析),typeof(崩溃));
MainPage=ServiceProvider.GetRequiredService();
}
公共静态IServiceCollection服务{get;}=newServiceCollection();
公共IServiceProvider服务提供程序{get;set;}
私有void配置服务(){
Services.AddSingleton();
Services.AddTransient();
RegisterLocalDataServices();
RegisterRemoteDataServices();
registerSyncologic();
RegisterServices();
RegisterViews();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton(DependencyService.Get());
Services.AddSingleton();
Services.AddSingleton();
ServiceProvider=Services.BuildServiceProvider();
}
公共无效注册表服务(){
Services.AddTransient();
Services.AddTransient();
Services.AddTransient();
Services.AddTransient();
}
公共无效注册表LocalDataServices(){
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
}
公共无效注册表RemotedataServices(){
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
}
公共无效注册表syncologic(){
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
}
public void RegisterViews(){
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
Services.AddTransient();
Services.AddSingleton();
}
受保护的重写异步void OnStart(){
等待ServiceProvider.GetRequiredService().OnStart();
}
受保护的覆盖void OnSleep(){}
受保护的重写异步void OnResume(){
等待ServiceProvider.GetRequiredService().OnResume();
}
由TAPONANDROIDNotification启动的公共无效(字符串消息){
_startedByAndroidNotificationMessage=消息;
}
}
}
多次创建的单例就是这些单例。可能是其他的单身汉也被创造了很多次,但我确信这些
Services.AddSingleton<IQueueOrchestrator, IncomingQueueOrchestrator>();
Services.AddSingleton<IQueueOrchestrator, OutgoingQueueOrchestrator>();
Services.AddSingleton<IQueueOrchestrator, PictureQueueOrchestrator>();
Services.AddSingleton<IQueueProcessor, IncomingQueueProcessor>();
Services.AddSingleton<IQueueProcessor, OutgoingQueueProcessor>();
Services.AddSingleton<IQueueProcessor, PictureQueueProcessor>();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
Services.AddSingleton();
我看到,在解析ILifecycleHooksService的依赖项时,有时会多次调用OnStart方法来创建这些单例的多个实例。这是LifecycleHookService中的代码:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Peripass.YardAssetManagementApp.Data;
using Peripass.YardAssetManagementApp.Data.LocalDataServices;
using Peripass.YardAssetManagementApp.Data.Syncing;
using Peripass.YardAssetManagementApp.MVVM;
using Peripass.YardAssetManagementApp.PushNotifications;
using Peripass.YardAssetManagementApp.ViewModels;
namespace Peripass.YardAssetManagementApp {
public interface ILifecycleHooksService {
Task OnStart();
Task OnResume();
}
public class LifecycleHooksService : ILifecycleHooksService {
private readonly INavigationService _navigationService;
private readonly ILocalUserDataService _localUserDataService;
private readonly ILocalTaskDataService _localTaskDataService;
private readonly ILocalLocationDataService _localLocationDataService;
private readonly ILocalPushNotificationDataService _localPushNotificationDataService;
private readonly ILocalPictureDataService _localPictureDataService;
private readonly IToMobileTasksSyncer _toMobileTasksSyncer;
private readonly IEnumerable<IQueueProcessor> _queueProcessors;
private readonly IPushNotificationsService _pushNotificationsService;
private readonly ILocalLocalizationDataService _localLocalizationDataService;
public LifecycleHooksService(INavigationService navigationService,
ILocalUserDataService localUserDataService,
IToMobileTasksSyncer toMobileTasksSyncer,
IEnumerable<IQueueProcessor> queueProcessors,
ILocalTaskDataService localTaskDataService,
ILocalLocationDataService localLocationDataService,
ILocalPushNotificationDataService localPushNotificationDataService,
IPushNotificationsService pushNotificationsService,
ILocalPictureDataService localPictureDataService, ILocalLocalizationDataService localLocalizationDataService) {
_navigationService = navigationService;
_localUserDataService = localUserDataService;
_toMobileTasksSyncer = toMobileTasksSyncer;
_queueProcessors = queueProcessors;
_localTaskDataService = localTaskDataService;
_localLocationDataService = localLocationDataService;
_localPushNotificationDataService = localPushNotificationDataService;
_pushNotificationsService = pushNotificationsService;
_localPictureDataService = localPictureDataService;
_localLocalizationDataService = localLocalizationDataService;
}
public async Task OnStart() {
await ReloadData();
await CreateDeviceIdOnFirstStartAsync();
var currentUser = _localUserDataService.GetCurrentUser();
if (currentUser.IsLoggedIn) {
Configuration.Configuration.SetEnvironment(currentUser.Environment);
await _navigationService.NavigateToViewModelAsync<MainTaskListViewModel>(true);
try {
await _toMobileTasksSyncer.SyncAllMetaData();
}
catch {
// ignored
}
}
else {
await _navigationService.NavigateToViewModelAsync<LoginViewModel>();
}
foreach (var queueProcessor in _queueProcessors) {
_ = Task.Run(async () => await queueProcessor.StartPeriodicProcessing());
}
}
public async Task OnResume() {
try {
await _toMobileTasksSyncer.SyncAllTasks(true);
}
catch {
// ignored
}
}
public async Task CreateDeviceIdOnFirstStartAsync() {
var currentPushNotificationInfo = await _localPushNotificationDataService.GetCurrentPushNotificationInfo();
if (string.IsNullOrEmpty(currentPushNotificationInfo.DeviceIdTag)) {
await _localPushNotificationDataService.SetDeviceId(Guid.NewGuid().ToString());
}
}
private async Task ReloadData() {
await _localLocalizationDataService.ReloadData();
await _localUserDataService.ReloadData();
await _localTaskDataService.ReloadData();
await _localLocationDataService.ReloadData();
await _localPictureDataService.ReloadData();
await _pushNotificationsService.ProcessReceivedMessages();
}
}
}
使用系统
// Possible work around for market launches. See https://issuetracker.google.com/issues/36907463
// for more details. Essentially, the market launches the main activity on top of other activities.
// we never want this to happen. Instead, we check if we are the root and if not, we finish.
if (!isTaskRoot()) {
final Intent intent = getIntent();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && Intent.ACTION_MAIN.equals(intent.getAction())) {
Log.w(LOG_TAG, "Main Activity is not the root. Finishing Main Activity instead of launching.");
finish();
return;
}
}