Xamarin.forms 如何在XAML中使用DI

Xamarin.forms 如何在XAML中使用DI,xamarin.forms,prism,Xamarin.forms,Prism,我希望我不是在想象,但我想我在Prism和XF中看到了一种在XAML中使用依赖注入的行为: <ContentPage.Behaviors> <helpers:MyPageBehavior> <x:Arguments> Have a type here maybe? </x:Arguments> </helpers:MyPageBehavior>

我希望我不是在想象,但我想我在Prism和XF中看到了一种在XAML中使用依赖注入的行为:

 <ContentPage.Behaviors>
   <helpers:MyPageBehavior>
      <x:Arguments>
             Have a type here maybe?
      </x:Arguments>             
   </helpers:MyPageBehavior>        
  </ContentPage.Behaviors>

也许这里有一种?
MyPageBehavior:

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

假设我们有一个类
SomeService
,它实现了
isomoservice
,如下所示:

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>

假设我们有一个类
SomeService
,它实现了
isomoservice
,如下所示:

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>

您需要使用
容器提供程序。您可以从下面的示例中看到如何使用它。您会注意到模拟转换器要求通过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;
        }
    }
}
使用系统;
利用制度全球化;
使用Xamarin.Forms;
使用Prism.Forms.Tests.Mocks.Events;
使用Prism.Events;
命名空间Prism.Forms.Tests.Mocks.converter
{
公共类MockValueConverter:IValueConverter
{
私有IEventAggregator_eventaggerator{get;}
public MockValueConverter(IEventAggregator事件生成器)
{
_eventAggreator=eventAggreator;
}
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
_eventAggreator.GetEvent().Publish(“转换”);
返回值;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
_EventAgCreator.GetEvent().Publish(“ConvertBack”);
返回值;
}
}
}
模拟视图

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

您需要使用
容器提供程序。您可以从下面的示例中看到如何使用它。您会注意到模拟转换器要求通过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;
        }
    }
}
使用系统;
利用制度全球化;
使用Xamarin.Forms;
使用Prism.Forms.Tests.Mocks.Events;
使用Prism.Events;
命名空间Prism.Forms.Tests.Mocks.converter
{
公共类MockValueConverter:IValueConverter
{
私有IEventAggregator_eventaggerator{get;}
public MockValueConverter(IEventAggregator事件生成器)
{
_eventAggreator=eventAggreator;
}
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
_eventAggreator.GetEvent().Publish(“转换”);
返回值;
}
公共对象转换回(对象值、类型targetType、对象参数、CultureInfo区域性)
{
_EventAgCreator.GetEvent().Publish(“ConvertBack”);
返回值;
}
}
}
模拟视图

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


谢谢。这是可行的,但问题是它不使用依赖注入,它只是实例化作为参数给出的类型。例如,如果
SomeService
注册为singleton,您将看到它的c-tor被调用两次,如果导航到此页面,返回并再次导航到它。我想到的第一件事是使用
ServiceLocator
。您可以看看这个答案,例如:。正如丹S.在回答中所建议的那样。但请记住,
ServiceLocator
被视为反模式。所以慢慢来做这样的决定吧。谢谢!我认为在某些情况下使用服务定位器非常有意义,这就是其中之一。谢谢。这是可行的,但问题是它不使用依赖注入,它只是实例化作为参数给出的类型。例如,如果
SomeService
注册为singleton,您将看到它的c-tor被调用两次,如果导航到此页面,返回并再次导航到它。我想到的第一件事是使用
ServiceLocator
。您可以看看这个答案,例如:。正如丹S.在回答中所建议的那样。但请记住,
ServiceLocator
被视为反模式。所以慢慢来做这样的决定吧。谢谢!我认为在某些情况下使用服务定位器是非常有意义的,这就是其中之一!我没有产生幻觉:)谢谢丹尼尔!你和布莱恩·拉古纳斯,你们太棒了!真讨厌!我没有产生幻觉:)谢谢丹尼尔!你和布莱恩·拉古纳斯,你们太棒了!