You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prism中向需无参构造函数的类注入服务的正确方案是什么

Prism中向必须使用无参构造函数的类注入服务的解决方案

WPF DataGrid开启新增行功能时,默认会直接调用绑定集合元素类型的无参构造函数创建新实例,这个创建过程不经过Prism的DI容器,所以不管是构造函数注入还是默认的属性注入都无法生效,你之前[Inject]标记不生效也是这个原因。

方案1:接管DataGrid的新增逻辑(推荐,侵入性最低)

不需要给MyModelWrapper加无参构造函数,只要处理DataGrid.AddingNewItem事件,手动创建已经注入好服务的MyModelWrapper实例即可:

  1. 首先在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);
    }
}
  1. 处理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方法手动触发属性注入:

  1. 调整MyModelWrapper定义,给需要注入的属性加[Inject]标记(必须为public属性):
public class MyModelWrapper : BindableBase
{
    [Inject]
    public IMyModelWrapperService Service { get; set; }

    // 保留无参构造给DataGrid调用
    public MyModelWrapper()
    {
    }

    // 保留原有带参构造用于手动创建
    public MyModelWrapper(IMyModelWrapperService service)
    {
        Service = service;
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 08:15:04