Acceptme3
@Acceptme3

Почему пустует DI контейнер при корректном добавлении сервисов?

Проект на ASP .Net Core MVC. База данных MS SQL Server. Взаимодействие с бд, с помощью EF Core. Написал класс для инициализации созданных в нем списков данными из базы. Класс написан по шаблону "Singlton" , так как необходим один экземпляр этого класса.

Код класса инициализатора:
Код класса инициализатора

using VartanMVCv2.Domain.Repositories.Abstract;
using VartanMVCv2.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using System.Diagnostics;

namespace VartanMVCv2.Domain
{
    public class Modelinitializer : IDisposable
    {
        private static readonly Lazy<Modelinitializer> instanceLazy = new Lazy<Modelinitializer>(()=>new Modelinitializer());
        private bool _disposed = false;

        private readonly IEntityRepository<WorkServices> _workServicesRepository;
        private readonly IEntityRepository<WorksList> _worksListRepository;
        private readonly IEntityRepository<WorksName> _workNameRepository;
        private readonly IEntityRepository<CompletedProject> _completedProjectRepository;
        private readonly IEntityRepository<CompletedProjectPhoto> _completedProjectPhotoRepository;
        private readonly IEntityRepository<Feedback> _feedbackRepository;

        private readonly ILogger<Modelinitializer> _logger;

        private readonly DbContext _dbContext;

        public List<WorkServices> workServicesList { get; set; } = new List<WorkServices>();
        public List<WorksList> worksList { get; set; } = new List<WorksList>();
        public List<WorksName> worksNameList { get; set; } = new List<WorksName>();
        public List<CompletedProject> completedProjectsList { get; set; } = new List<CompletedProject>();
        public List<CompletedProjectPhoto> completedProjectPhotosList { get; set; } = new List<CompletedProjectPhoto>();
        public List<Feedback> feedbackList { get; set; } = new List<Feedback>();

        public bool InitialFlag { get; protected set; } = false;

        private Modelinitializer() 
        {
            
        }


        public Modelinitializer(IEntityRepository<WorkServices> workServicesRepository, IEntityRepository<WorksList> worksListRepository, IEntityRepository<WorksName> workNameRepository, IEntityRepository<CompletedProject> completedProject, IEntityRepository<CompletedProjectPhoto> completedProjectPhoto, IEntityRepository<Feedback> feedback, AplicationDBContext appDBContext, ILogger<Modelinitializer> logger)
        {
            _workServicesRepository = workServicesRepository;
            _worksListRepository = worksListRepository;
            _workNameRepository = workNameRepository;
            _completedProjectRepository = completedProject;
            _completedProjectPhotoRepository = completedProjectPhoto;
            _feedbackRepository = feedback;

            _dbContext = appDBContext;

            _logger = logger;
        }

        public static Modelinitializer CreateInstance ()
        {
            return instanceLazy.Value;           
        }

        public async Task ModelInitialAsync()
        {
            if (_workServicesRepository == null) 
            {
                Debug.WriteLine("DI conteiner is empty");
            }
            workServicesList = await _workServicesRepository.GetAllAsync();
            worksList = await _worksListRepository.GetAllAsync();
            worksNameList = await _workNameRepository.GetAllAsync();
            completedProjectsList = await _completedProjectRepository.GetAllAsync();
            completedProjectPhotosList = await _completedProjectPhotoRepository.GetAllAsync();
            feedbackList = await _feedbackRepository.GetAllAsync();



            _logger.LogInformation($"Инициализация списков, в рамках вызова метода ModelInitialAsync () завершена. Колличество элементов WorkServices: {workServicesList.Count} \n" +
                $"WorksList: {worksList.Count} \n" +
                $"WorksName: {worksNameList.Count} \n" +
                $"CompletedProjectList: {completedProjectsList.Count} \n" +
                $"CompletedProjectPhoto: {completedProjectPhotosList.Count} \n" +
                $"Feedback: {feedbackList.Count}");  
            InitialFlag = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing) 
        {
            if (_disposed) return;
            if (disposing) 
            {
                // позже нужно реализовать удаление управляемых ресурсов 
            }
            // тут очистка неуправляемых ресурсов
            _disposed = true;
        }
        ~Modelinitializer() 
        {
            Dispose(false);
        }
    }
}


Репозиторий с CRUD методами подключил как сервис в DI контейнере. Вроде все везде корректно. Но при запуске приложения, вылетает System.NullReferenceException: "Object reference not set to an instance of an object." В Чем может быть дело? Почему экземпляры репозитория а вместе с ним и логгера не регестрируются в контейнере?
Класс Program(не копировал маршруты)

using VartanMVCv2.Domain.Entities;

namespace VartanMVCv2
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            // add services
            builder.Services.AddControllersWithViews().AddSessionStateTempDataProvider();
            //сопостовляем конфигурационный json с классом
            builder.Configuration.AddJsonFile("appsettings.json");
            Config config = new Config();
            builder.Configuration.Bind("Project", config);
            //подключаем класс контекста базы данных
            builder.Services.AddDbContext<AplicationDBContext>(x => x.UseSqlServer(Config.ConnectionString));
            //подключаем нужный функционал в качестве сервисов
            builder.Services.AddMemoryCache();
            builder.Services.AddTransient<Modelinitializer>();
            builder.Services.AddTransient<IEntityRepository<WorkServices>, EFEntitiesRepository<WorkServices>>();
            builder.Services.AddTransient<IEntityRepository<WorksList>, EFEntitiesRepository<WorksList>>();
            builder.Services.AddTransient<IEntityRepository<WorksName>, EFEntitiesRepository<WorksName>>();
            builder.Services.AddTransient<IEntityRepository<CompletedProject>, EFEntitiesRepository<CompletedProject>>();
            builder.Services.AddTransient<IEntityRepository<CompletedProjectPhoto>, EFEntitiesRepository<CompletedProjectPhoto>>();
            builder.Services.AddTransient<IEntityRepository<Feedback>, EFEntitiesRepository<Feedback>>();
            
            builder.Services.AddTransient<DataManager>();
            builder.Services.AddTransient<IndexViewModel>();
            
            //настраиваем Identity 
            builder.Services.AddIdentity<IdentityUser, IdentityRole>(opts =>
            {
                opts.User.RequireUniqueEmail = false;
                opts.Password.RequiredLength = 6;
                opts.Password.RequireNonAlphanumeric = false;
                opts.Password.RequireLowercase = false;
                opts.Password.RequireUppercase = false;
                opts.Password.RequireDigit = false;
            }).AddEntityFrameworkStores<AplicationDBContext>().AddDefaultTokenProviders();
            //autentificatio cookie
            builder.Services.ConfigureApplicationCookie(options =>
            {
                options.Cookie.Name = "MyCompanyAuth";
                options.Cookie.HttpOnly = true;
                options.LoginPath = "/account/login";
                options.AccessDeniedPath = "/account/accesdenied";
                options.SlidingExpiration = true;
            });

            var app = builder.Build();


Исключение:
spoiler

System.NullReferenceException
HResult=0x80004003
Сообщение = Object reference not set to an instance of an object.
Источник = VartanMVCv2
Трассировка стека:
в VartanMVCv2.Domain.Modelinitializer.d__41.MoveNext() в C:\Users\Дмирий\source\repos\Acceptme3\VartanMVCv2\Domain\Modelinitializer.cs:строка 64

Вот это вот все сервисы репозитория

builder.Services.AddTransient<IEntityRepository<WorkServices>, EFEntitiesRepository<WorkServices>>();
            builder.Services.AddTransient<IEntityRepository<WorksList>, EFEntitiesRepository<WorksList>>();
            builder.Services.AddTransient<IEntityRepository<WorksName>, EFEntitiesRepository<WorksName>>();
            builder.Services.AddTransient<IEntityRepository<CompletedProject>, EFEntitiesRepository<CompletedProject>>();
            builder.Services.AddTransient<IEntityRepository<CompletedProjectPhoto>, EFEntitiesRepository<CompletedProjectPhoto>>();
            builder.Services.AddTransient<IEntityRepository<Feedback>, EFEntitiesRepository<Feedback>>();

  • Вопрос задан
  • 123 просмотра
Решения вопроса 1
Acceptme3
@Acceptme3 Автор вопроса
насколько я понимаю, проблема в следующем. В классе инициализатора два конструктора: конструктор по умолчанию, приватный, инициализирует объект в который не попадают сервисы из DI контейнера т.к для этого определяется пользовательский конструктор с параметрами. Получается в итоге создается больше одного объекта инициализатора . Как это обойти? знаю что ответ простой но уже не одупляю.

UPD. Решил проблему выносом списков с данными в класс и его уже сделал одиночкой.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@DBalashov
Ошибка говорит о том, что ошибка не в регистрации сервисов, а внутри GetAllAsync при foreach или материализации запроса.

workServicesList = await _workServicesRepository.GetAllAsync();
Ответ написан
yarosroman
@yarosroman Куратор тега C#
C# the best
Попробуйте убрать конструктор без параметров в Modelinitializer.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы