如何在 XAML 中使用 DI

How to use DI in XAML

我希望我不是在想象,但我想我在 Prism 和 XF 的某个地方看到了一种方法,可以在 XAML:

中使用依赖注入的行为
 <ContentPage.Behaviors>
   <helpers:MyPageBehavior>
      <x:Arguments>
             Have a type here maybe?
      </x:Arguments>             
   </helpers:MyPageBehavior>        
  </ContentPage.Behaviors>

我的页面行为:

class MyPageBehavior : Behavior<ContentPage>
{
      public MyPageBehavior(ISomeService someService)
      {
      }
}

假设我们有 class SomeService 实现 ISomeService,如下所示:

namespace YOURAPPNAME.Services
{
     public class SomeService : ISomeService
     {
          public SomeService()
          {
              Debug.WriteLine("Some Service Constructor Called");
          }
     }
}

然后在您的 Xaml 页面中

<ContentPage ......
         xmlns:services="clr-namespace:YOURAPPNAME.Services;assembly=YOURAPPNAME"
         .....>

<ContentPage.Behaviors>
   <helpers:MyPageBehavior>
      <x:Arguments>
         <services:SomeService />
      </x:Arguments>             
   </helpers:MyPageBehavior>        
</ContentPage.Behaviors>

您需要使用 ContainerProvider。您可以从下面取自 Prism Unit Tests 的示例中看到如何使用它。您会注意到 Mock Converter 需要通过 DI 注入 IEventAggregator。在 XAML 中,您可以使用 ContainerProvider 并传入转换器的类型参数,将转换器添加到 ResourceDictionary。

模拟转换器

using System;
using System.Globalization;
using Xamarin.Forms;
using Prism.Forms.Tests.Mocks.Events;
using Prism.Events;

namespace Prism.Forms.Tests.Mocks.Converters
{
    public class MockValueConverter : IValueConverter
    {
        private IEventAggregator _eventAggreator { get; }

        public MockValueConverter(IEventAggregator eventAggreator)
        {
            _eventAggreator = eventAggreator;
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            _eventAggreator.GetEvent<TestActionEvent>().Publish("Convert");
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            _eventAggreator.GetEvent<TestActionEvent>().Publish("ConvertBack");
            return value;
        }
    }
}

模拟视图

<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:prism="clr-namespace:Prism.Ioc;assembly=Prism.Forms"
    xmlns:converters="using:Prism.Forms.Tests.Mocks.Converters"
    Title="{Binding Title}"
    x:Class="Prism.DI.Forms.Tests.Mocks.Views.XamlViewMock">
    <ContentPage.Resources>
        <ResourceDictionary>
            <prism:ContainerProvider x:TypeArguments="converters:MockValueConverter" x:Key="mockValueConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <Entry x:Name="testEntry"
        Text="{Binding Test,Converter={StaticResource mockValueConverter}}" />
</ContentPage>