Caliburn Micro构造函数注入失败

时间:2013-07-23 05:42:22

标签: c# dependency-injection caliburn.micro eventaggregator

我正在学习Caliburn Micro,并尝试使用official site中的EventAggregator

然而,我得到了一个例外

  

“没有为此对象定义无参数构造函数。”

消息本身很清楚,但示例中也没有包含无参数构造函数。如果我添加一个,则不会触发带参数的构造函数,并且仍未正确注入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溶液。

我想念什么?

2 个答案:

答案 0 :(得分:9)

// ... Other Bootstrapper Config

这是另一个重要的bootstrapper配置。

最好的选择是通过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>();
     }
}

答案 1 :(得分:9)

devdigital是正确的。他说

  

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

这是完全正确的。

如果您要使用DI SimpleContainer为您执行此操作),那么必须覆盖引导程序中的GetInstance(), GetAllInstances(), BuildUp()方法,因为CM在需要容器中的内容时调用这些方法。

你的情况如下:

  1. CM尝试显示您的MainViewModel,因为您已将其指定为Bootstrapper中的通用参数。
  2. CM注意到您的MainViewModel有一个带IEventAggregator的构造函数。
  3. CM致电GetInstance()以获取注册为IEventAggregator的任何内容。
  4. CM指出您没有覆盖GetInstance(),因此它尝试使用MainViewModel创建Activator.CreateInstance()的实例。
  5. Activator.CreateInstance()不知道如何创建IEventAggregator,因此它会抛出异常(您正在获得的那个)
  6. 要解决所有这些问题,你必须覆盖我告诉你的方法。您不需要安装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);
            }
    
        }
    
相关问题