Поскольку в действии вашего контроллера вам нужен экземпляр IRepository<Employee>
, вы можете использовать любой из этих двух методов, если зарегистрированная услуга относится к этому типу (в вашем втором подходе вы регистрировали его как EmployeeRepository
):
services.AddSingleton<IRepository<Employee>, EmployeeRepository>();
services.AddSingleton<IRepository<Employee>>(new EmployeeRepository());
Как вы можете прочитать в документах , разница между этими двумя параметрами - это всего лишь точка, в которой будет создан экземпляр.
- При использовании первого варианта экземпляр будет создан при первом запуске службы в каком-либо классе.
- Со вторым вариантом экземпляр создается вручную вами в
ConfigureServices
.
Какой из них следует использовать, зависит от ваших потребностей.
Что касается того, почему вы получили его как null, в вашем проекте должно быть что-то еще, проверьте наличие ошибок в консоли или попытайтесь воспроизвести проблему в новом минимальном проекте. Я попытался воспроизвести его, но оба метода регистрации работали нормально:
- Новое веб-приложение 1.0.1
-
Затем добавили следующие типы:
public class Employee { }
public interface IRepository<T> { }
public class EmployeeRepository: IRepository<Employee> { }
-
Обновлено действие Index в HomeController для получения экземпляра, используя [FromServices]
:
public IActionResult Index([FromServices]IRepository<Employee> emp)
РЕДАКТИРОВАТЬ
Как упоминалось в @Tseng , вы не должны вызывать BuildServiceProvider
метод Startup:
- Это означает, что вы создаете собственного поставщика услуг, полностью отделенного от того, который создаст ASP.Net Core.
- Это также означает, что экземпляр, который вы получите в методе Startup, отличается от того, который получит ваш контроллер (поскольку у каждого поставщика услуг будет свой собственный синглтон)
Либо оставьте фактическое создание экземпляра поставщику услуг, либо используйте второй AddSingleton
метод, если вам нужно создать экземпляр самостоятельно. Не беспокойтесь, если ваш класс также нуждается в сервисах в своем конструкторе, поставщик услуг будет нуждаться в том, как их разрешать, если они были зарегистрированы в Startup.
Например, обновите свое репо, чтобы сохранить в памяти статический список сотрудников:
public class EmployeeRepository : IRepository<Employee>
{
private List<string> employees = new List<string>();
public void Create(string employeeId)
{
this.employees.Add(employeeId);
}
}
Затем добавьте нового сотрудника каждый раз, когда вы вызываете действие индекса:
public IActionResult Index([FromServices]IRepository<Employee> repo)
{
repo.Create($"client-{ Guid.NewGuid() }");
return View();
}
Вы увидите, что независимо от того, какой из двух способов регистрации одного синглета вы используете, ваш контроллер всегда будет получать один и тот же экземпляр, а сотрудники будут добавлены в один список.
Имейте в виду еще один комментарий @Tseng , где он упоминает, что одноэлемент, вероятно, не самый лучший вариант для репозитория. Обычно это зависит от некоторого DbContext, который создается для каждого запроса. (Если вы не создаете какую-либо форму поставщика DbContext, и ваше репо зависит от него, но это не по теме)