Как внедрить зависимость представления в Presenter (MVP) в веб-формах ASP. NET с помощью Simple Injector или Microsoft.Extensions.Dependency? - PullRequest
0 голосов
/ 17 июня 2020

В следующем примере показан сценарий, в котором я пытаюсь реализовать контейнер DI. В этом случае я пытаюсь использовать простой инжектор или контейнер DI Microsoft.Extensions.DependencyInjection. Я видел примеры кода, которые начинают поражать цель, например здесь , но пока нет "яблочка".

Ниже приведен общий образец кода, который я хотел бы изменить для использования один из вышеупомянутых контейнеров DI (например, Used Simple Injector). Я мог бы переместить представление из конструктора презентатора и установить его как свойство. Однако я надеялся на более красноречивое решение, и это зависимость, которую необходимо ввести.

Я знаю. NET 4.7.2 увеличила функциональность поддержки DI, но самое большое преимущество, похоже, состоит в том, что зависимости легко вставляются в страницы / пользовательские элементы управления. Для архитектуры MVP мне нужен конкретный класс страницы, привязанный к ее интерфейсу представления, чтобы контейнер DI мог разрешить и передать в презентатор, поскольку презентатор зависит от представления. Я не видел примера такой реализации, кроме Unity, использующей DependencyOverride, который может передавать конкретный класс во время выполнения.

public partial class UserLoginView : IUserLoginView
{    
    private UserLoginPresenter _userLoginPresenter;

    protected override void OnLoad(EventArgs e)
    {    
         //This is my problem:
         //An error will be thrown "...contains the parameter with name 
         //'view' and type IUserLoginView, but IUserLoginView is not 
         //registered..."    
         _userLoginPresenter = SimpleInjectorDependencyInjector
            .GetInstance<IDeveloperTestStatusPresenter>();
    }
}

public class UserLoginPresenter : IUserLoginPresenter
{
    private readonly IUserLoginView view;
    private readonly IUserService _userService;

    public UserLoginPresenter(IUserLoginView userLoginView,
        IUserService userService)
    {
        this.view = userLoginView;
        this._userService = userService;
    }


public static class SimpleInjectorDependencyInjector
{
    private static readonly Container container = new Container();

    public static T GetInstance<T>() where T : class
    {
        return container.GetInstance<T>();
    }

    //Assume this is called from App on start
    public static void RegisterClasses()
    {           
        container
            .Register<IUserLoginPresenter, UserLoginPresenter>();
        container
            .Register<IUserService, UserService>();
    }
}

1 Ответ

0 голосов
/ 25 июня 2020

Мне удалось выполнить sh то, что я искал, с помощью контейнера Microsoft.Extensions.DependencyInjection.

В моем классе-оболочке MSDependencyInjector я использовал расширение ActivatorUtilities.

public static T GetService<T, I>(I interfaceInstance)
{
    return ActivatorUtilities.CreateInstance<T>(container, interfaceInstance);
}

Реализовано в частичном классе моей страницы, о котором я писал:

 _userLoginPresenter = MSDependencyInjector.GetService<UserLoginPresenter,
                IUserLoginView>(this);

Предостережение: параметр 'T' createInstance требует конкретного типа класса, а не интерфейса. Это вызвало многочасовое разочарование, в первую очередь вызвав возникновение этого вопроса. Документация MS не самая лучшая, но я определенно неправильно ее прочитал.

Я не уверен, как реализовать что-то столь же простое в Simple Injector, и мне было бы интересно узнать. Основываясь на моем чтении, я не уверен, не является ли мое решение чем-то вроде локатора услуг, которого следует избегать в зависимости от того, из какого вы лагеря. Однако, если реализация этого может быть ограничена просто для решения потребности в этой парадигме MVP, я надеюсь, что все будет хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...