如何使用StructureMap将服务注入到从XAML引用的ViewModel中?

时间:2013-08-05 11:20:06

标签: c# wpf xaml dependency-injection structuremap

我可能会说这一切都错了,但我认为我走的是正确的道路。我是第一次构建WPF应用程序,我仍然习惯于完成某些工作。

我的想法

  • 我的目标是让我的ViewModel类更具可测试性。
  • ViewModel依赖于服务类,没有它就无法运行。
  • 因此,将服务注入ViewModel似乎是有意义的,这样我也可以开始模拟它以进行测试。

我做了什么

  • 对我的视图模型进行了XAML引用,称为“UploaderViewModel”:
 <Window.DataContext>
     <viewModels:UploaderViewModel>
         </viewModels:UploaderViewModel>
 </Window.DataContext>

注意:在我尝试进行注射之前这很好用

  • 在我的app.xaml.cs文件中设置结构图:
   void App_Startup(object sender, StartupEventArgs eventArgs)
    {
        ContainerBootstrapper.BootstrapStructureMap();
        ProcessStartupArguments(eventArgs);
    }

调用我的bootstrapper类:

public static class ContainerBootstrapper
{
    public static void BootstrapStructureMap()
    {
        ObjectFactory.Initialize(
            x => x.For<IVEDocumentService>().Use<VEDocumentService>()
            );
    }
}
  • 然后让我的UploaderViewModel类将IVEDocumentService作为Constructor参数:

    public UploaderViewModel(IVEDocumentService documentService)
    {
        _documentService = documentService;
        //other unrelated code below this
     }
    

出了什么问题

我收到一条XAML错误,指出没有为ViewModel找到默认构造函数,这是有道理的,因为我没有UploaderViewModel(),只有UploaderViewModel(IVEDocumentService documentService)

问题

  • 解决此问题的最佳方法是什么?
  • 我应该创建一个UploaderViewModel()构造函数,并使用该服务的实例使StructureMap调用UploaderViewModel,还是有更好的方法?

更新1 - 尝试使用资源字典,StructureMap错误。

根据此SO Answer to a similar question,我尝试了:

  • 更新我的App_Startup以将UploaderViewModel的实例添加到资源字典:
void App_Startup(object sender, StartupEventArgs eventArgs)
{
  ContainerBootstrapper.BootstrapStructureMap();

var uploaderViewModel = new UploaderViewModel(new Container().GetInstance<IVEDocumentService>());
Current.Resources["UploaderViewModel"] = uploaderViewModel;

ProcessStartupArguments(eventArgs);

}
  • 在我的DataContext="{StaticResource UploaderViewModel}"声明
  • 中添加了<Window>
  • 注释掉我的<viewModels:UploaderViewModel/>声明

执行此操作后,StructureMap现在抛出错误:

  

“StructureMap异常代码:202没有为。定义的默认实例   PluginFamily

1 个答案:

答案 0 :(得分:1)

我明白了。我想我没有正确配置静态资源。使用StructureMap的解决方案是执行以下操作:

App.xaml.cs

   void App_Startup(object sender, StartupEventArgs eventArgs)
    {
        ContainerBootstrapper.BootstrapStructureMap();
        //Other logic
     }

ContainerBootstrapper类

public static void BootstrapStructureMap()
{
    ObjectFactory.Initialize(x => x.For<IVEDocumentService>().Use<VEDocumentService>());
}

MainWindow.xaml.cs

我将资源创建移到了这个类中:

public MainWindow()
{
    var uploaderViewModel = new UploaderViewModel(ObjectFactory.GetInstance<IVEDocumentService>());
    this.Resources["UploaderViewModel"] = uploaderViewModel;
    InitializeComponent();
}

MainWindow.xaml

<Window>定义中,我设置了DataContext="{StaticResource UploaderViewModel}"

像魅力一样工作。我认为这是在适当的范围(窗口)没有绑定资源的组合。