我正在使用autofac解析WPF应用程序中的视图和ViewModels。IComponentContext将自动传递到视图中。
举个例子:
public BusinessAuto(int proposedCoverageId, IComponentContext componentContext)
{
DataContext = componentContext.Resolve<BusinessAutoViewModel>(new TypedParameter(typeof(Int32), proposedCoverageId));
InitializeComponent();
}
在用于此视图的XAML中,正在创建具有自己的UserControls的ViewModels。举个例子:
<userControl:AdditionalCoveragesControl Margin="0,10"/>
Autofac没有创建UserControl (视图是),因此Autofac不能将依赖项注入UserControl的构造函数。
如何将对IComponentContext的引用转换为初始视图的XAML?中声明的UserControl
我觉得我要么需要Autofac来以某种方式创建我的UserControl,要么我需要恢复到气馁的全局静态容器( ick),或者我必须使用一个DependencyProperty来传递容器(也是ick)。
发布于 2013-01-05 01:37:54
我不会注入(实际上是什么)您的容器,因为这是一种称为Service的控制反转的低级形式,其缺陷可以用当前的情况来总结:您最终需要将容器注入到所有东西中。
相反,您需要从“负责创建的组件是什么,以及它需要做什么”的角度来处理这个问题?
正如Lonni所提到的,一种选择是注入一个完全形成的控件,但我不同意这一点:如果主视图负责创建这个子组件,那么它应该创建它--但是为了方便这种责任,您应该将主视图注入服务/模型/等等,然后它需要传递或以其他方式使用来创建它。Autofac的工厂方法存根对此非常理想:
例如,如果子视图需要一个IFooViewModel,您可以向容器注入一个Func
(或者您需要的Func )
一个方便的经验法则是,当考虑到X类时,首先在任何地方“更新”任何内容,然后将其传递给构造函数。现在看看代码,问问自己“如果我想要一个类X的实例,我需要什么来传递构造函数?”这些是你的依赖关系。
让我们使用更多的example...say,您有这样的结构:
所以我们的领队看起来是:
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了。
发布于 2013-01-05 01:21:49
您不应该将componentContext传递给BusinessAuto视图,而应该传递AdditionalCoveragesControl。
public BusinessAuto(int proposedCoverageId, BusinessAutoViewModel vm, AdditionalCoveragesControl view)
{
...
DataContext = vm;
InternalView = view;
}
XAML:
<ContentPresenter Content="{Binding InternalView}" Margin="0,10"/>
然后您的所有视图都将独立于Autofac,您应该将它们全部注册在容器中。
https://stackoverflow.com/questions/13845903
复制相似问题