2013-07-23 42 views
10

我在学习Caliburn Micro,并尝试使用official site中的EventAggregatorCaliburn微型构造器注入失败

但是,我得到了一个异常

“这个对象定义无参数的构造函数。”

消息本身很明显,但该示例并未包含无参数构造函数。如果我添加一个,带参数的构造函数没有命中,并且IEventAggregator仍未正确注入。

这里是我的出版商VM添加参数的构造函数后(没有它,将引发异常):

public MainViewModel() { } 

    public MainViewModel(IEventAggregator ea) : this() 
    { 
     eventAggregator = ea; 
    } 

这里是我使用的引导程序:

public class AppBootstrapper : Bootstrapper<MainViewModel> 
{ 
    private readonly SimpleContainer container = new SimpleContainer(); 

    protected override void Configure() 
    { 
     container.Singleton<IEventAggregator, EventAggregator>(); 
    } 
} 

这里是从CM的例子:

// Creating the EventAggregator as a singleton. 
public class Bootstrapper : BootstrapperBase { 
    private readonly SimpleContainer _container = 
     new SimpleContainer(); 

    // ... Other Bootstrapper Config 

    protected override void Configure(){ 
     _container.Singleton<IEventAggregator, EventAggregator>(); 
    } 

    // ... Other Bootstrapper Config 
} 

// Acquiring the EventAggregator in a viewModel. 
public class FooViewModel { 
    private readonly IEventAggregator _eventAggregator; 

    public FooViewModel(IEventAggregator eventAggregator) { 
     _eventAggregator = eventAggregator; 
    } 
} 

我检查了这个帖子(Inject EventAggregator into ViewModel with Caliburn Micro),但它只是不说为什么CM不用注入来调用构造函数。

我也检查了CM的样品解决方案,但它使用MEF作为DI解决方案。

我错过了什么?

+0

它已经有一段时间,因为我看着卡利,但你肯定你的引导程序实际上是启动,可以得到的情况下,等?查看这个http://caliburnmicro.codeplex.com/SourceControl/latest#samples/Caliburn.Micro.HelloSimpleContainer/Caliburn.Micro.HelloSimpleContainer/Bootstrapper.cs简单容器示例,它不使用MEF或任何其他 –

+0

@MaksimS。 Configure()被执行;我试图将Start()添加到引导程序构造函数,但没有运气。此外,该示例不会在虚拟机中注入任何内容。 – ender

+0

目前没有任何东西来测试您的代码;然而,只是看看最新版本中的EventAggregator代码,它_does_包含无参数的构造函数,至少在micro.wpf中。你是否有机会使用Prism的EventAggregator,或者其他的东西,而不是Caliburn的?我知道这听起来很愚蠢,但仍然:) –

回答

8
// ... Other Bootstrapper Config 

这是其他重要的引导程序配置。

最好的办法是通过Caliburn.Micro.Start NuGet包安装Caliburn.Micro,并看看提供的引导程序也使用由Caliburn.Micro提供的SimpleContainer

这是在充分:

public class AppBootstrapper : BootstrapperBase 
{ 
    SimpleContainer container; 

    public AppBootstrapper() 
    { 
     Start(); 
    } 

    protected override void Configure() 
    { 
     container = new SimpleContainer(); 
     container.Singleton<IWindowManager, WindowManager>(); 
     container.Singleton<IEventAggregator, EventAggregator>(); 
     container.PerRequest<IShell, ShellViewModel>(); 
    } 

    protected override object GetInstance(Type service, string key) 
    { 
     var instance = container.GetInstance(service, key); 
     if (instance != null) 
      return instance; 
     throw new InvalidOperationException("Could not locate any instances."); 
    } 

    protected override IEnumerable<object> GetAllInstances(Type service) 
    { 
     return container.GetAllInstances(service); 
    } 

    protected override void BuildUp(object instance) 
    { 
     container.BuildUp(instance); 
    } 

    protected override void OnStartup(object sender, System.Windows.StartupEventArgs e) 
    { 
     DisplayRootViewFor<IShell>(); 
    } 
} 
+0

谢谢,我会试试这个。 – ender

8

devdigital是正确的。他说

这是另一个引导程序配置是重要的。

这是完全正确的。

如果你要使用DI (其中SimpleContainer为你做)那么你必须覆盖在你的引导程序的GetInstance(), GetAllInstances(), BuildUp()方法,因为CM调用这些方法时,它想从容器中的东西。

什么是您的情况发生的事情是这样的:

  1. CM尽量展示MainViewModel因为你指定其作为引导程序的泛型参数。
  2. CM注意到您的MainViewModel有一个构造函数需要IEventAggregator
  3. CM致电GetInstance()获取任何注册为IEventAggregator的内容。
  4. CM指出您没有覆盖GetInstance(),因此它会尝试使用Activator.CreateInstance()创建MainViewModel的实例。
  5. Activator.CreateInstance()不知道如何创建一个IEventAggregator所以它会抛出一个异常(你正在得到的)

要解决所有这些,你必须覆盖我告诉你的方法。您不需要安装Nuget Caliburn.Start软件包(如果您不喜欢打字并且您想节省一些击键次数,您可以使用它)

本质上你的最终解决方案应该是这样的:

public class Bootstrapper : Bootstrapper<MainViewModel> 
    { 

     private readonly SimpleContainer _container = new SimpleContainer(); 

     protected override void Configure() 
     { 
      _container.Instance<IWindowManager>(new WindowManager()); 
      _container.Singleton<IEventAggregator, EventAggregator>(); 
      _container.PerRequest<MainViewModel>(); 
     } 

     protected override object GetInstance(Type service, string key) 
     { 
      return _container.GetInstance(service, key); 
     } 

     protected override IEnumerable<object> GetAllInstances(Type service) 
     { 
      return _container.GetAllInstances(service); 
     } 

     protected override void BuildUp(object instance) 
     { 
      _container.BuildUp(instance); 
     } 

    } 
+1

很好的解释,谢谢。 – Nestor