c# – 将Autofac容器传递给WPF UserControl
我正在使用autofac来解析
WPF应用程序中的Views和ViewModel. IComponentContext将自动传递到View中.
一个例子: public BusinessAuto(int proposedCoverageId,IComponentContext componentContext) { DataContext = componentContext.Resolve<BusinessAutoViewModel>(new TypedParameter(typeof(Int32),proposedCoverageId)); InitializeComponent(); } 在此视图的XAML中,创建了具有自己的ViewModel的UserControl.一个例子: <userControl:AdditionalCoveragesControl Margin="0,10"/> Autofac不会创建UserControl(View是),因此Autofac无法将依赖项注入UserControl的构造函数中. 如何将对IComponentContext的引用转换为在初始View的XAML中声明的UserControl? 我觉得我要么需要Autofac以某种方式创建我的UserControl,我需要恢复到不鼓励的全局静态容器(ick),或者我必须使用DependencyProperty来传递容器(也是ick). 解决方法
我不会注入(有效的)你的容器,因为这是一种称为服务定位器的低级控制反转形式,缺点可以通过你当前的情况来总结:你最终需要将容器注入一切.
相反,您需要从“负责创建的这个组件是什么,以及它需要做什么?”的角度来解决问题. 正如Lonni-Loki所提到的,一个选择是注入一个完全形成的控件,但我不同意这一点:如果主视图有责任创建这个子组件,那么它应该创建它 – 但为了促进这个责任,你应该注入主视图与服务/模型/等,然后需要传递或以其他方式用于创建它. Autofac的工厂方法存根非常适用于此: 例如,如果子视图需要IFooViewModel,则可以使用Func< IFooViewModel< (在上下文中注册的工厂方法),然后它可以用于“按需提供”新包含的视图. (或Func< arg1,arg2等,IFooViewModel>,根据您的需要) 一个方便的经验法则是在考虑X类时,首先在任何地方“新建”任何东西,然后将其传递给构造函数.现在看看代码并问自己“如果我想要一个X类的实例,我需要传递什么构造函数?”那些是你的依赖. 让我们来看一个更实际的例子…说你有这样的结构: >应用程序创建MainWindow 所以我们的ctors看起来像: public MainWindow(IMainWindowViewModel viewModel,Func<SubView1> subView1Factory) public SubView1(ISubView1Model viewModel,IFooService fooService,Func<IFooService,SubView2> subView2Factory) public SubView2( ISubView2ModelViewModel viewModel,IBarService barService) 在设置容器时,你会有这样的事情: (注意,我使用了各种IoC容器,因此我的Autofac语法可能会生锈) var builder = new ContainerBuilder(); // Simple bit,register implementations for viewmodel,services builder.RegisterType<MainWindowViewModel>.As<IMainWindowViewModel>(); builder.RegisterType<SubView1Model>.As<ISubView1Model>(); builder.RegisterInstance<FooService>.As<IFooService>(); // ok,lemme see if I can remember expression syntax... // Simple case: 'static' resolution of subview // We want a func that takes no args and returns us a fully-initialized // SubView1 builder.Register<Func<SubView1>>(context => { // Since all the bits of a subview1 are registered,simply // resolve it and return var view = context.Resolve<SubView1>(); return () => view; }); // Complicated case - lets say this viewmodel depends // on foo service,which it uses to determine which // bar service to use builder.Register<Func<IFooService,SubView2>>(context => { // and our view model var vm = context.Resolve<ISubView2ViewModel>(); return (service) => { var barService = new BarService(service); return new SubView2(vm,barService); }; }); 光荣(在我看来,仅限于)IoC容器的使用是“你弄清楚如何根据我已经告诉你的东西得到所有的部分” – 否则,你不妨使用手动注射,你在哪里手工传递依赖关系.也就是说,我们可能复杂的MainWindow构建现在只是: container.Resolve<MainWindow>(); 我希望我没有在代码中输入太多的拼写错误/错误,但我还没有使用Autofac一段时间. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |