Caliburn Micro构造函数注入失败

end*_*der 11 c# dependency-injection eventaggregator caliburn.micro

我学习卡利微并尝试使用的EventAggregator官方网站.

但是,我有一个例外

"没有为此对象定义无参数构造函数."

消息本身很清楚,但示例中也没有包含无参数构造函数.如果我添加一个,带有参数的构造函数不会被命中,IEventAggregator仍然没有正确注入.

添加无参数构造函数后,这是我的发布者VM(没有它,将抛出异常):

    public MainViewModel() { }

    public MainViewModel(IEventAggregator ea) : this()
    {
        eventAggregator = ea;
    }
Run Code Online (Sandbox Code Playgroud)

这是我正在使用的引导程序:

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

    protected override void Configure()
    {
        container.Singleton<IEventAggregator, EventAggregator>();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我检查了这篇文章(用Caliburn Micro将EventAggregator注入ViewModel),但它简单地说没有为什么CM不用注入调用构造函数.

我还检查了CM的样品溶液,但它使用MEF作为DI溶液.

我错过了什么?

dev*_*tal 9

// ... Other Bootstrapper Config
Run Code Online (Sandbox Code Playgroud)

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

最好的选择是通过Caliburn.Micro.Start NuGet包安装Caliburn.Micro ,并查看提供的引导程序,它也使用SimpleContainerCaliburn.Micro提供的.

这里是完整的:

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>();
     }
}
Run Code Online (Sandbox Code Playgroud)


Ibr*_*jar 9

devdigital是正确的.他说

它是另一个重要的bootstrapper配置.

这是完全正确的.

如果您打算使用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如此它抛出异常(你得到的那个).

要解决所有这些问题,你必须覆盖我告诉你的方法.您不需要安装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);
        }

    }
Run Code Online (Sandbox Code Playgroud)