Могу ли я сделать идентификацию частью контейнера при создании контроллеров MVC?

#c# #inversion-of-control #identity

Вопрос:

Когда мой контроллер использует объект, который принимает идентификатор в качестве входных данных, я, конечно, мог бы сделать это:

 public class MyController : ControllerBase {  private readonly MyRepository _repository;   public MyController()  {  _repository = new MyRepository(HttpContext.User.Identity);  } }  

Однако ручное создание репозитория (или любого другого объекта, который нуждается в идентификации) не очень изящно. Лучшим способом было бы использовать контейнер IOC для введения идентификатора

Есть ли способ добавить идентификатор в контейнер IOC, чтобы я мог просто сделать это:

 public class MyController : ControllerBase {  private readonly MyRepository _repository;   public MyController(MyRepository repository)  {  _repository = repository;  } }  

Идентичность, конечно, полезна во всех видах объектов. Его можно использовать в репозитории БД для добавления метаданных, таких как обновление пользователя. Или он может быть использован объектом, обращающимся к другой службе для олицетворения

Комментарии:

1. У вас может быть интерфейс IIdentityProvider в качестве зависимости от репозитория. У него должен быть метод или свойство для возврата идентификатора. И реализующий класс должен получить доступ к идентификатору из HttpContext и вернуться в реализующем свойстве или методе.

2. Но тогда должен ли конструктор IdentityProvider иметь HttpContext в качестве параметра в конструкторе ? Тогда мне нужно было бы зарегистрировать HttpContext в контейнере. Разве это не та же самая проблема ?

3. В этом нет необходимости… Ваш класс должен иметь прямой доступ HttpContext.User.Identity . класс будет просто оболочкой HttpContext.User.Identity и не будет зависеть от HttpContext.

Ответ №1:

Вдохновленный предложением @Chetan, но немного по-другому, это сработало для меня. Я добавил эти регистрации в свой стартап:

 services.AddHttpContextAccessor();  services.AddScopedlt;IIdentityProvider, IdentityProvidergt;();  

Первая строка сделает IHttpContextAccessor доступным для инъекции. Затем я могу построить свою личность, как это:

 internal class IdentityProvider : IIdentityProvider {  public IdentityProvider(IHttpContextAccessor contextAccessor)  {  Identity = contextAccessor.HttpContext?.User.Identity;  }   public IIdentity Identity { get; } }  

Затем IIdentityProvider будет доступен для MyRepository и других объектов, где это необходимо

 public class MyRepository {  private readonly IIdentity _identity;   public MyRepository(IIdentityProvider identityProvider)  {  _identity = identityProvider.Identity;  } }