Внедрение конструктора в классы файлов Xamarin Froms .xaml.cs

Я хочу воспользоваться преимуществами внедрения зависимостей в моем проекте Xamarin, но не могу заставить конструкторскую инъекцию работать в классах C # за представлениями XAML. Есть ли способ это сделать? Я видел руководства по настройке инъекций зависимостей в моделях представления, чтобы впоследствии использовать их в качестве репозиториев, но у меня это не работает.

Пока что пробовал Ninject и Unity.

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

public class MyService : IMyService
{
    public void Add(string myNote)
    {
        //Add Note logic
    }
}

Интерфейс:

 public interface IMyService
 {
    void Add(string myNote);
 }

Настройка Unity в App.Xaml:

public App ()
{
   InitializeComponent();

    var unityContainer = new UnityContainer();
     unityContainer.RegisterType<IMyService, MyService>();

    var unityServiceLocator = new UnityServiceLocator(unityContainer);              
    ServiceLocator.SetLocatorProvider(() => unityServiceLocator);

    MainPage = new MainMasterMenu(); //<-- feel that I'm missing something here as I shouldn't be creating class instances with DI, right ?
}

Использование, которое я хотел бы увидеть. Это файл .CS за стартовой страницей XAML:

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainMasterMenu : MasterDetailPage
{
    private IMyService _myService;
    public MainMasterMenu(IMyService myService)
    {
      _myService = myService
    }

   private void SomeFormControlClickEvent(object sender, ItemChangedEventArgs e)
    {
     _myService.Add("hi");
    }
}

person InspiredBy    schedule 13.08.2018    source источник


Ответы (1)


Для этого простого примера создание MainMasterMenu напрямую не будет проблемой, но вам нужно будет передать ссылку на свою службу

MainPage = new MainMasterMenu(unityContainer.Resolve<IMyService>());

Но это будет означать, что вам придется изменять эту строку каждый раз, когда изменяется конструктор MainMasterMenu. Вы можете обойти это, также зарегистрировав MainMasterMenu.

unityContainer.RegisterType<MainMasterMenu>();
...
MainPage = unityContainer.Resolve<MainMasterPage>();

В любом случае, в любое время, когда вы хотите перейти на другую страницу, для которой нужна какая-либо зависимость, зарегистрированная с помощью unity, вам необходимо убедиться, что ее зависимости правильно разрешены, что требует (по крайней мере, косвенного) доступа к контейнеру unity. Вы можете передать оболочку, которая инкапсулирует доступ к единству

interface IPageResolver
{
    T ResolvePage<T>()
        where T : Page;
}

а затем реализовать этот резолвер с единицей

public class UnityPageResolver
{
    private IUnityContainer unityContainer;

    public UnityPageResolver(IUnityContainer unityContainer)
    {
        this.unityContainer = unityContainer;
    }

    public T ResolvePage<T>()
        where T : Page // do we need this restriction here?
    {
        return unityContainer.Resolve<T>();
    }
}

Это регистрируется с единством

unityContainer.RegisterInstance<IUnityContainer>(this);
unityContainer.RegisterType<IPageResolver, UnityPageResolver>();

Но вам следует взглянуть на библиотеку Prism (см. Здесь), которая решает многие проблемы (например, он предоставляет INavigationService, который позволяет вам переходить к другим страницам, не заботясь о зависимостях, и предоставляет средства для автоматического разрешения моделей просмотра, включая зависимости).

person Paul Kertscher    schedule 13.08.2018
comment
Спасибо. Я попробую и сообщу об этом. - person InspiredBy; 17.08.2018