rab*_*woo 5 uac dependency-injection inversion-of-control uwp template10
我花了两个多星期的时间搜索 google、bing、stack overflow 和 msdn 文档,试图找出如何为我正在开发的移动应用程序进行适当的依赖注入。需要明确的是,我每天都在 Web 应用程序中进行 DI。我不需要关于什么、谁以及为什么 DI 很重要的速成课程。我知道它是,并且我总是拥抱它。
我需要了解的是这在移动应用程序世界中是如何工作的,尤其是 UWP 模板 10 移动应用程序。
从我过去开始,在 .net/Asp 应用程序中,我可以“RegisterType(new XYZ).Singleton() blah”{请原谅语法;只是 App_Start.ConfigureServices 中的一个示例}。这在 .netcore 中的工作原理几乎相同,但进行了一些语法更改。
我的问题是现在我试图将我的 api 提供给需要消化我的 IXYZ 服务的 UWP 应用程序。我绝不认为他们应该每次都“新建”一个实例。必须有一种方法将其注入 UWP 端的容器中;我觉得我在这个过程中遗漏了一些非常简单的东西。
这是我的代码:
应用程序.xaml.cs
public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
// TODO: add your long-running task here
//if (args.Kind == ActivationKind.LockScreen)
//{
//}
RegisterServices();
await NavigationService.NavigateAsync(typeof(Views.SearchCompanyPage));
}
public static IServiceProvider Container { get; private set; }
private static void RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<IXYZ, XYZ>();
Container = services.BuildServiceProvider();
}
Run Code Online (Sandbox Code Playgroud)
MainPage.xaml.cs:
public MainPage()
{
InitializeComponent();
NavigationCacheMode = NavigationCacheMode.Enabled;
}
Run Code Online (Sandbox Code Playgroud)
主页面视图模型:
public class MainPageViewModel : ViewModelBase
{
private readonly IXYZ _xyz;
public MainPageViewModel(IXYZ xyz)
{
//Stuff
_xyz= xyz;
}
}
Run Code Online (Sandbox Code Playgroud)
我现在收到错误消息: 无法构造 XAML MainPage...ViewModel 类型。为了在 XAML 中构造,类型不能是抽象的、接口嵌套的泛型或结构,并且必须具有公共默认构造函数。
我愿意使用任何品牌的 IoC Container,但我需要的是如何在 UWP 应用程序中正确使用 DI 服务的示例。99.9% 的关于 DI 的问题是关于视图(即 Prism?),而不仅仅是服务的简单 DI(即 DataRepo;又名 API/DataService)。
再次,我觉得我错过了一些明显的东西,需要朝正确的方向推动。有人可以向我展示一个示例项目、基本代码或关于我不应该成为程序员的基本信息...请不要那样做(我不知道我的自我是否可以接受)。
在 @mvermef 和 SO 问题Dependency Injection using Template 10的帮助下,我找到了一个解决方案。事实证明,这是一个兔子洞,我每次都会遇到问题。
第一个问题是让依赖注入发挥作用。一旦我能够从上面的来源中弄清楚这一点,我就能够开始将我的服务注入到 ViewModel 中,并将它们设置到后面代码中的 DataContext 中。
然后,我在将 IXYZ 服务注入 UserControls 的 ViewModel 时遇到了注入问题。
页面及其 ViewModel 工作得很好,但我遇到了 UserControl 的 DataContext 未注入 UserControl 的 ViewModel 的问题。相反,它们是由持有它的页面的 ViewModel 注入的。
最终的解决方案是确保 UserControl在XAML中设置 DataContext ,而不是在后面的代码中设置,就像我们对页面所做的那样,然后在后面的代码中创建 DependencyProperty。
要显示基本解决方案,请阅读下文。
为了让它发挥作用,我从以下开始:
应用程序XAML.CS
public override async Task OnStartAsync(StartKind startKind, IActivatedEventArgs args)
{
// long-running startup tasks go here
RegisterServices();
await Task.CompletedTask;
}
private static void RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<IRepository, Repository>();
services.AddSingleton<IBinderService, BinderServices>();
**//ViewModels**
**////User Controls**
services.AddSingleton<AddressesControlViewModel, AddressesControlViewModel>();
services.AddSingleton<CompanyControlViewModel, CompanyControlViewModel>();
**//ViewModels**
**////Pages**
services.AddSingleton<CallListPageViewModel, CallListPageViewModel>();
services.AddSingleton<CallListResultPageViewModel, CallListResultPageViewModel>();
etc....
Container = services.BuildServiceProvider();
}
public override INavigable ResolveForPage(Page page, NavigationService navigationService)
{
**//INJECT THE VIEWMODEL FOR EACH PAGE**
**//ONLY THE PAGE NOT USERCONTROL**
if (page is CallListPage)
{
return Container.GetService<CallListPageViewModel>();
}
if (page is CallListResultPage)
{
return Container.GetService<CallListResultPageViewModel>();
}
etc...
return base.ResolveForPage(page, navigationService);
}
Run Code Online (Sandbox Code Playgroud)
在页面后面的代码中
调用列表页.XAML.CS
public CallListPage()
{
InitializeComponent();
}
CallListPageViewModel _viewModel;
public CallListPageViewModel ViewModel
{
get { return _viewModel ?? (_viewModel = (CallListPageViewModel)DataContext); }
}
Run Code Online (Sandbox Code Playgroud)
在您的 XAML 中添加您的 UserControl
调用列表页.XAML
<binder:CompanyControl Company="{x:Bind ViewModel.SelectedCompany, Mode=TwoWay}"/>
在您的 UserControl 中,确保将 DataContext 添加到 XAML,而不是像我们对页面所做的那样添加到后面的代码。
公司控制.XAML
<UserControl.DataContext>
<viewModels:CompanyControlViewModel x:Name="ViewModel" />
</UserControl.DataContext>
Run Code Online (Sandbox Code Playgroud)
在 UserControl 代码后面添加一个依赖属性
公司控制.XAML.CS
public static readonly DependencyProperty CompanyProperty = DependencyProperty.Register(
"Company", typeof(Company), typeof(CompanyControl), new PropertyMetadata(default(Company), SetCompany));
public CompanyControl()
{
InitializeComponent();
}
public Company Company
{
get => (Company) GetValue(CompanyProperty);
set => SetValue(CompanyProperty, value);
}
private static void SetCompany(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as CompanyControl;
var viewModel = control?.ViewModel;
if (viewModel != null)
viewModel.Company = (Company) e.NewValue;
}
Run Code Online (Sandbox Code Playgroud)
最后,我不确定这是否是一个优雅的解决方案,但它确实有效。
| 归档时间: |
|
| 查看次数: |
4095 次 |
| 最近记录: |