为什么我的 Autofac 注册的 Prism EventAggregator 没有正确注入到视图模型中?
Why my Autofac registered Prism EventAggregator is not injected properly into viewmodel?
在我的解决方案中,我使用了 Autofac 和 Prism。下面是一个简化的项目,解释了会发生什么。
我正在 Autofac 的容器 class 中注册我的视图、视图模型和 EventAggregator
:
public class BootStrapper
{
public IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<EventAggregator>()
.As<IEventAggregator>().SingleInstance();
builder.RegisterType<MainWindow>().AsSelf();
builder.RegisterType<ChildView1>().AsSelf();
builder.RegisterType<MainViewModel>().AsSelf();
builder.RegisterType<Child1ViewModel>().AsSelf();
return builder.Build();
}
}
注意,将视图模型注册为单例时,效果是一样的。我像这样将 EventAggregator
注入我的虚拟机:
public class MainViewModel
{
private IEventAggregator _eventAggregator;
public MainViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
UpdateName("Name1");
}
public void UpdateName(string name)
{
ChildView1 win1 = new ChildView1(); //in the backend Child1ViewModel is assigend to its DataContext
win1.Show();
_eventAggregator.GetEvent<UpdateNameEvent>().Publish(name); //this does not work
}
}
上面的代码不起作用。因为某些原因(希望大家告诉我为什么),在执行UpdateName
方法时,这个依赖不起作用,在Child1ViewModel[里面=54=] class UpdateName
方法未执行:
public class Child1ViewModel : ViewModelBase
{
private IEventAggregator _eventAggregator;
public Child1ViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
private void UpdateName(string name)
{
this.Name = name; //debug does not hit this code line
}
}
Child1ViewModel 的构造函数在调试期间被 hiten,只是 UpdateName
没有被执行。但是,如果我使用 EventAggregator
的直接调用,就像这样:
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
或者这个:
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Publish(name);
有效!假设 Utility class 看起来像:
public class Utility
{
public static EventAggregator EventAggregator { get; set; }
static Utility()
{
EventAggregator = new EventAggregator();
}
}
我怀疑在 Autofac 中注册聚合器存在一些问题,但我不知道是什么问题,我只是按照我发现的 odl exaples 使用它.
正在解析 Child1ViewModel 和 MainViewModel:
public partial class ChildView1 : Window
{
public ChildView1()
{
var bootStrapper = new BootStrapper();
var container = bootStrapper.BootStrap();
Child1ViewModel vm = container.Resolve<Child1ViewModel>();
InitializeComponent();
DataContext = vm;
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
var bootStrapper = new BootStrapper();
var container = bootStrapper.BootStrap();
MainViewModel vm = container.Resolve<MainViewModel>();
InitializeComponent();
DataContext = vm;
}
}
我假设您正在使用 Prism 的 ViewModelLocator 机制。我的假设是基于您手动实例化 ChildView1 而不是使用依赖注入容器解析它,并在评论中声明 viewModel 在后台解析。
您必须更改用于解析 ViewModel 实例的 Prism ViewModelLocator 容器,如下所示。
ViewModelLocationProvider.SetDefaultViewModelFactory(viewModelType) =>
{
return YourAutofacContainer.Resolve<viewModelType>();
});
有关详细信息,请参阅 Control how ViewModels are Resolved。
请记住,为了在整个应用程序中保持对象实例的单实例生命周期范围一致,您必须使用相同的依赖注入容器实例来解析对象和此对象的父对象,一直到根对象.
在我的解决方案中,我使用了 Autofac 和 Prism。下面是一个简化的项目,解释了会发生什么。
我正在 Autofac 的容器 class 中注册我的视图、视图模型和 EventAggregator
:
public class BootStrapper
{
public IContainer BootStrap()
{
var builder = new ContainerBuilder();
builder.RegisterType<EventAggregator>()
.As<IEventAggregator>().SingleInstance();
builder.RegisterType<MainWindow>().AsSelf();
builder.RegisterType<ChildView1>().AsSelf();
builder.RegisterType<MainViewModel>().AsSelf();
builder.RegisterType<Child1ViewModel>().AsSelf();
return builder.Build();
}
}
注意,将视图模型注册为单例时,效果是一样的。我像这样将 EventAggregator
注入我的虚拟机:
public class MainViewModel
{
private IEventAggregator _eventAggregator;
public MainViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
UpdateName("Name1");
}
public void UpdateName(string name)
{
ChildView1 win1 = new ChildView1(); //in the backend Child1ViewModel is assigend to its DataContext
win1.Show();
_eventAggregator.GetEvent<UpdateNameEvent>().Publish(name); //this does not work
}
}
上面的代码不起作用。因为某些原因(希望大家告诉我为什么),在执行UpdateName
方法时,这个依赖不起作用,在Child1ViewModel[里面=54=] class UpdateName
方法未执行:
public class Child1ViewModel : ViewModelBase
{
private IEventAggregator _eventAggregator;
public Child1ViewModel(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged();
}
}
private void UpdateName(string name)
{
this.Name = name; //debug does not hit this code line
}
}
Child1ViewModel 的构造函数在调试期间被 hiten,只是 UpdateName
没有被执行。但是,如果我使用 EventAggregator
的直接调用,就像这样:
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
或者这个:
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Publish(name);
有效!假设 Utility class 看起来像:
public class Utility
{
public static EventAggregator EventAggregator { get; set; }
static Utility()
{
EventAggregator = new EventAggregator();
}
}
我怀疑在 Autofac 中注册聚合器存在一些问题,但我不知道是什么问题,我只是按照我发现的 odl exaples 使用它.
正在解析 Child1ViewModel 和 MainViewModel:
public partial class ChildView1 : Window
{
public ChildView1()
{
var bootStrapper = new BootStrapper();
var container = bootStrapper.BootStrap();
Child1ViewModel vm = container.Resolve<Child1ViewModel>();
InitializeComponent();
DataContext = vm;
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
var bootStrapper = new BootStrapper();
var container = bootStrapper.BootStrap();
MainViewModel vm = container.Resolve<MainViewModel>();
InitializeComponent();
DataContext = vm;
}
}
我假设您正在使用 Prism 的 ViewModelLocator 机制。我的假设是基于您手动实例化 ChildView1 而不是使用依赖注入容器解析它,并在评论中声明 viewModel 在后台解析。
您必须更改用于解析 ViewModel 实例的 Prism ViewModelLocator 容器,如下所示。
ViewModelLocationProvider.SetDefaultViewModelFactory(viewModelType) =>
{
return YourAutofacContainer.Resolve<viewModelType>();
});
有关详细信息,请参阅 Control how ViewModels are Resolved。
请记住,为了在整个应用程序中保持对象实例的单实例生命周期范围一致,您必须使用相同的依赖注入容器实例来解析对象和此对象的父对象,一直到根对象.