Prism中向需无参构造函数的类注入服务的正确方案是什么
Prism中向必须使用无参构造函数的类注入服务的解决方案
WPF DataGrid开启新增行功能时,默认会直接调用绑定集合元素类型的无参构造函数创建新实例,这个创建过程不经过Prism的DI容器,所以不管是构造函数注入还是默认的属性注入都无法生效,你之前[Inject]标记不生效也是这个原因。
方案1:接管DataGrid的新增逻辑(推荐,侵入性最低)
不需要给MyModelWrapper加无参构造函数,只要处理DataGrid.AddingNewItem事件,手动创建已经注入好服务的MyModelWrapper实例即可:
- 首先在MyViewModel中注入需要的
IMyModelWrapperService,暴露创建实例的方法:
public class MyViewModel : BindableBase { private readonly IMyModelWrapperService _wrapperService; public ObservableCollection<MyModelWrapper> Items { get; } = new(); public MyViewModel(IMyModelWrapperService wrapperService) { _wrapperService = wrapperService; } public MyModelWrapper CreateNewWrapper() { return new MyModelWrapper(_wrapperService); } }
- 处理DataGrid的AddingNewItem事件,可以直接在View后台写,也可以用Prism的交互触发器绑定到ViewModel命令:
// View后台代码示例 private void DataGrid_AddingNewItem(object sender, AddingNewItemEventArgs e) { var vm = (MyViewModel)DataContext; e.NewItem = vm.CreateNewWrapper(); }
该方案不需要改动MyModelWrapper的结构,也不需要引入容器引用,完全符合DI规范。
方案2:使用Prism容器初始化无参构造创建的实例
如果必须保留MyModelWrapper的无参构造函数,可以注入IContainerProvider,调用BuildUp方法手动触发属性注入:
- 调整MyModelWrapper定义,给需要注入的属性加
[Inject]标记(必须为public属性):
public class MyModelWrapper : BindableBase { [Inject] public IMyModelWrapperService Service { get; set; } // 保留无参构造给DataGrid调用 public MyModelWrapper() { } // 保留原有带参构造用于手动创建 public MyModelWrapper(IMyModelWrapperService service) { Service = service; } }
- 在ViewModel中监听集合变化,初始化新增实例:
public class MyViewModel : BindableBase { private readonly IContainerProvider _containerProvider; public ObservableCollection<MyModelWrapper> Items { get; } = new(); public MyViewModel(IContainerProvider containerProvider) { _containerProvider = containerProvider; Items.CollectionChanged += Items_CollectionChanged; } private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems != null) { foreach (MyModelWrapper item in e.NewItems) { // 手动触发Prism的属性注入 _containerProvider.BuildUp(item); } } } }
方案3:使用抽象工厂封装创建逻辑
如果不想在ViewModel中依赖具体构造逻辑,可以定义工厂接口解耦:
public interface IMyModelWrapperFactory { MyModelWrapper Create(); } public class MyModelWrapperFactory : IMyModelWrapperFactory { private readonly IMyModelWrapperService _service; public MyModelWrapperFactory(IMyModelWrapperService service) { _service = service; } public MyModelWrapper Create() { return new MyModelWrapper(_service); } }
在App.xaml.cs中注册工厂:
protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.Register<IMyModelWrapperFactory, MyModelWrapperFactory>(); }
之后在ViewModel中注入工厂调用Create方法配合方案1使用即可。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

