【问题标题】:Constructor Injection in Xamarin Froms .xaml.cs file classesXamarin Forms .xaml.cs 文件类中的构造函数注入
【发布时间】:2019-01-19 17:30:46
【问题描述】:

我想在我的 Xamarin 项目中利用依赖注入,但无法让构造函数注入在 XAML 视图后面的 C# 类中工作。有什么办法吗? 我已经看到了如何在视图模型中设置依赖注入的指南,以便以后将它们用作存储库,但这对我不起作用。

到目前为止,我尝试了 Ninject 和 Unity。

代码: 这是我想在我的 PCL 项目中使用的服务:

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

界面:

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

App.Xaml 中的 Unity 设置:

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 ?
}

我希望看到的用法。这是 XAML 起始页后面的 .CS 文件:

[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");
    }
}

【问题讨论】:

    标签: c# xamarin dependency-injection xamarin.forms mobile-development


    【解决方案1】:

    对于这个简单的示例,直接创建 MainMasterMenu 没有问题,但您必须将引用传递给您的服务

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

    但这意味着每次MainMasterMenu 的构造函数更改时,您都必须更改该行。您也可以通过注册MainMasterMenu 来规避这种情况。

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

    无论如何,无论何时您想要导航到另一个页面,该页面需要使用 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 库 (see here)(例如,它提供了一个 INavigationService,让您可以导航到其他页面而无需关心依赖关系,它提供了解决问题的工具视图模型,包括依赖项)。

    【讨论】:

    • 谢谢。我会试一试,然后报告。
    猜你喜欢
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 2016-05-28
    • 2018-03-06
    • 1970-01-01
    • 2011-09-02
    相关资源
    最近更新 更多