如何将Unity IoC容器与Template10一起使用



我有一个基于Template10的应用程序,希望使用IoC处理依赖项注入。我倾向于使用Unity。我的应用程序分为三个程序集:

  1. UI(通用应用程序)
  2. UI逻辑(通用库)
  3. 核心逻辑(可移植库)

我有以下问题:

  1. 我应该为整个应用程序使用一个容器,还是为每个程序集创建一个容器
  2. 我应该在哪里创建容器并注册我的服务
  3. 不同程序集中的不同类应该如何访问容器?辛格尔顿模式

我读了很多关于DI和IoC的书,但我需要知道如何在实践中应用所有理论,特别是在Template10中。

要注册的代码:

// where should I put this code?
var container = new UnityContainer();
container.RegisterType<ISettingsService, RoamingSettingsService);

然后是检索实例的代码:

var container = ???
var settings = container.Resolve<ISettingsService>();

我不熟悉Unity Container

我的例子是使用LightInject,您可以使用Unity应用类似的概念。要在ViewModel上启用DI,您需要在项目的App.xaml.cs上覆盖ResolveForPage

public class MainPageViewModel : ViewModelBase
{
ISettingsService _setting;
public MainPageViewModel(ISettingsService setting)
{
_setting = setting;
}
}

[Bindable]
sealed partial class App : Template10.Common.BootStrapper
{
internal static ServiceContainer Container;
public App()
{
InitializeComponent();
}
public override async Task OnInitializeAsync(IActivatedEventArgs args)
{
if(Container == null)
Container = new ServiceContainer();
Container.Register<INavigable, MainPageViewModel>(typeof(MainPage).FullName);
Container.Register<ISettingsService, RoamingSettingsService>();
// other initialization code here
await Task.CompletedTask;
}
public override INavigable ResolveForPage(Page page, NavigationService navigationService)
{
return Container.GetInstance<INavigable>(page.GetType().FullName);
}
}

如果您想在MainPage.xaml.cs:上使用{x:bind}Template10将自动将DataContext设置为MainPageViewModel

public class MainPage : Page
{
MainPageViewModel _viewModel;
public MainPageViewModel ViewModel
{
get { return _viewModel??(_viewModel = (MainPageViewModel)this.DataContext); }
}
}

这里有一个如何使用Unity和Template 10的小例子。

1.创建ViewModel

我还创建了一个DataService类来创建人员列表。请查看[Dependency]注释。

public class UnityViewModel : ViewModelBase
{
public string HelloMessage { get; }
[Dependency]
public IDataService DataService { get; set; }
private IEnumerable<Person> people;
public IEnumerable<Person> People
{
get { return people; }
set { this.Set(ref people, value); }
}
public UnityViewModel()
{
HelloMessage = "Hello !";
}
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode,
IDictionary<string, object> suspensionState)
{
await Task.CompletedTask;
People = DataService.GetPeople();
}
}

2.创建一个类来创建并填充UnityContainer

将UnityViewModel和DataService添加到unityContainer中。创建一个属性来解析UnityViewModel。

public class UnitiyLocator
{
private static readonly UnityContainer unityContainer;
static UnitiyLocator()
{
unityContainer = new UnityContainer();
unityContainer.RegisterType<UnityViewModel>();
unityContainer.RegisterType<IDataService, RuntimeDataService>();
}
public UnityViewModel UnityViewModel => unityContainer.Resolve<UnityViewModel>();
}

3.将UnityLocator添加到您的应用程序中。xaml

<common:BootStrapper x:Class="Template10UWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:common="using:Template10.Common"
xmlns:mvvmLightIoc="using:Template10UWP.Examples.MvvmLightIoc"
xmlns:unity="using:Template10UWP.Examples.Unity">

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="StylesCustom.xaml" />
<ResourceDictionary>
<unity:UnitiyLocator x:Key="UnityLocator"  />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<!--  custom resources go here  -->
</ResourceDictionary>
</Application.Resources>

4.创建页面

使用UnityLocator将UnityViewModel设置为DataContext,并将属性绑定到控件

<Page
x:Class="Template10UWP.Examples.Unity.UnityMainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Template10UWP.Examples.Unity"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding Source={StaticResource UnityLocator}, Path=UnityViewModel}"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding HelloMessage}" HorizontalAlignment="Center"
VerticalAlignment="Center" />
<ListBox Grid.Row="1" ItemsSource="{Binding People}" DisplayMemberPath="FullName">
</ListBox>
</Grid>

当页面解析UnityViewModel时,将自动注入DataService。

现在回答您的问题

  1. 这取决于项目如何相互依赖。我不确定什么是最好的解决方案,但我想我会尝试使用一个UnityContainer并将其放在核心库中。

  2. 我希望我的例子能回答这个问题

  3. 我希望我的例子能回答这个问题

最新更新