如何在Ninject解析依赖时添加参数?WPF MVVM实践疑问
针对你在开发包含UserControls的ItemsControl时遇到的ViewModel创建问题,我来一步步帮你梳理解决方案:
一、简化初始ViewModel列表的写法
你最初的循环代码可以用LINQ链式调用简化,让代码更简洁紧凑:
var viewModels = Enum.GetValues(typeof(DataModel)) .Cast<DataModel>() .Select(type => { var vm = ViewModelLocator.Get<IDataViewModel>(); vm.Type = type; return vm; }) .ToList();
这样就把原来的foreach循环转换成了声明式的LINQ操作,可读性和简洁性都更好。
不过如果想在创建ViewModel时直接传递参数(避免后续手动设置Type属性),工厂模式确实是更优雅的方案,也就是你后来尝试的方向。
二、工厂模式下无法创建新实例的问题
你提到首次调用工厂能创建新实例,但后续调用得到的是同一个对象,这是因为Ninject默认的绑定生命周期是单例(Singleton)——也就是说,一旦创建过一个IDataViewModel实例,后续所有请求都会返回这个实例。
解决方法很简单,只需要在绑定ViewModel时指定Transient生命周期,让Ninject每次请求都创建新的实例:
public class ViewModelModule : NinjectModule { public override void Load() { // 关键:设置为TransientScope,每次请求都生成新实例 Bind<IDataViewModel>().To<DataViewModel>().InTransientScope(); Bind<IViewModelFactory>().ToFactory(); } }
另外你自己发现的点非常关键:工厂接口的方法参数必须和ViewModel的构造函数签名完全匹配!
比如你的DataViewModel需要添加一个接收枚举参数的构造函数,这样Ninject的工厂扩展才能自动把参数传递进去:
public class DataViewModel : IDataViewModel { // 构造函数必须匹配工厂方法的参数类型 public DataViewModel(DataModel type) { Type = type; } public DataModel Type { get; set; } // 其他接口实现逻辑... }
这样修改后,工厂调用CreateDataViewModel(type)时,就会自动创建带对应参数的新ViewModel实例,不需要再手动设置Type属性。
三、关于工厂接口的多余方法疑问
你不需要为每个枚举值单独定义一个Create方法!Ninject的工厂扩展会根据方法的参数自动匹配对应的构造函数,一个CreateDataViewModel方法就足够处理所有枚举值的情况,定义多个方法反而会增加冗余,完全没必要。
内容的提问来源于stack exchange,提问作者Tristan Trainer

