Xamarin.forms 如何在XAML中使用DI
我希望我不是在想象,但我想我在Prism和XF中看到了一种在XAML中使用依赖注入的行为: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>
<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
被视为反模式。所以慢慢来做这样的决定吧。谢谢!我认为在某些情况下使用服务定位器是非常有意义的,这就是其中之一!我没有产生幻觉:)谢谢丹尼尔!你和布莱恩·拉古纳斯,你们太棒了!真讨厌!我没有产生幻觉:)谢谢丹尼尔!你和布莱恩·拉古纳斯,你们太棒了!