通过Autofac容器WPF用户控件 [英] Pass Autofac container to WPF UserControl

查看:2293
本文介绍了通过Autofac容器WPF用户控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用autofac解决WPF应用程序的意见和的ViewModels。 。IComponentContext被传递到自动查看

I am using autofac to resolve Views and ViewModels in a WPF application. IComponentContext is being passed into the View automatically.

一个例子:

    public BusinessAuto(int proposedCoverageId, IComponentContext componentContext)
    {
        DataContext = componentContext.Resolve<BusinessAutoViewModel>(new TypedParameter(typeof(Int32), proposedCoverageId));
        InitializeComponent();
    }

在XAML对这一观点有创建用户控件拥有自己的ViewModels 。举个例子:

In the XAML for this view there are UserControls being created that have their own ViewModels. An example:

<userControl:AdditionalCoveragesControl Margin="0,10"/>



Autofac没有创建用户控件(视图是),所以Autofac不能把依赖注入UserControl的构造函数。

Autofac is not creating the UserControl (the View is) so Autofac cannot inject dependencies into the UserControl's constructor.

我要如何才能到达IComponentContext成在初始视图的XAML声明的用户控件参考?

我觉得我要么需要Autofac以某种方式创建我的用户,我需要恢复到泄气的全局静态容器(益),或者我必须使用的DependencyProperty传递的容器里(也ICK )。

I feel that I either need Autofac to somehow create my UserControl, that I need to revert to the discouraged Global static container (ick), or I have to use a DependencyProperty to pass the container down (also ick).

推荐答案

我不会注入(什么是有效)的容器,因为这是控制反转的形式低劣所谓的服务定位,与可由你目前的情况来总结不足之处:你最终需要注入容器到一切

I wouldn't inject (what is effectively) your container, as this is an inferior form of inversion of control called Service Locator, with deficiencies that can be summed up by your current situation: you end up needing to inject the container into EVERYTHING.

相反,你需要处理这个问题从视图的角度什么是负责创建的这一部分,它有什么需要做的吗?

Instead, you need to approach the problem from the point of view of "What is this component in charge of creating, and what does it need to do it?"

正如Lonni - 洛基所提到的,一个选项是注入一个完全成型的控制,但我不同意这一点:如果主视图具有创建此子组件的责任,那么它应该创建它 - 但方便的责任,你应该注入的服务/型号主视图在/ etc那就再需要一起传递或以其他方式使用来创建它。 Autofac的工厂方法存根是非常理想的:

As mentioned by Lonni-Loki, one option is to inject a fully formed control but I disagree on that point: if the main view has the responsibility of creating this sub component, then it should create it - but to facilitate that responsibility, you should inject the main view with the services/models/etc it would then need to pass along or otherwise use to create it. Autofac's factory method stubs are ideal for this:

例如,如果子视图需要一个IFooViewModel,你可以注入一个Func键<容器; IFooViewModel< (注册与上下文工厂方法),它可以再使用新的包含视图按需喂养

For example if the sub view needs an IFooViewModel, you can inject the container with a Func<IFooViewModel< (a factory method registered with the context), which it can then use to "feed on demand" the new contained view.

(或函数求< ARG1,ARG2,等IFooViewModel>中为您的需求要求)

(or a Func<arg1, arg2, etc, IFooViewModel>, as your needs require)

拇指的一个方便的原则考虑类X时,先取任何你的新达什么,而是传递到构造函数。现在看代码,并问自己如果我想要类X的一个实例,我会需要通过构造函数? ,这些都是你的依赖

One handy rule of thumb is when considering class X, first take anywhere you "new up" anything and instead pass that into the constructor. Now look at the code and ask yourself "If I wanted an instance of class X, what would I need to pass the constructor?" Those are your dependencies.

让我们更实际的例子...说你有这样的结构:

Let's take a more hands-on example...say you've got a structure like this:


  • 应用程序创建主窗口

  • Application creates MainWindow

主窗口创建SubView1,需要IMainWindowViewModel

MainWindow creates SubView1, needs IMainWindowViewModel

SubView1需要ISubView1Model,IFooService

SubView1 needs ISubView1Model, IFooService

SubView1创建SubView2

SubView1 creates SubView2

SubView2需要ISubView2Model,IBarService

SubView2 needs ISubView2Model, IBarService

因此,我们构建函数看起来像:

So our ctors would look like:

public MainWindow(IMainWindowViewModel viewModel, 
     Func<SubView1> subView1Factory)

public SubView1(ISubView1Model viewModel,
    IFooService fooService,
    Func<IFooService, SubView2> subView2Factory)

public SubView2(
    ISubView2ModelViewModel viewModel, 
    IBarService barService)

当设置您的容器,你必须像这样:

When setting up your container, you'd have something like so:

(注意,我用了各种的IoC容器,所以我Autofac语法可能生锈)

(note, I use a variety of IoC containers, so my Autofac syntax might be rusty)

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容器中,是你弄清楚如何获得基于什么我已经告诉过你的一部分,所有位 - 否则,你还不如用手动进样,你在依赖传递手。这就是说,我们的潜在复杂的主窗口的建设,现在仅仅是:

The glorious (and in my opinion, only) use for IoC containers is the "You figure out how to get all the bits based on what I've already told you" part - otherwise, you might as well use manual injection, where you pass in dependencies by hand. That said, our potentially complicated construction of MainWindow is now just:

container.Resolve<MainWindow>();



我希望我没有在代码中做出太多的错别字/错误,但我没有二手Autofac一会儿。

I hope I didn't make too many typos/errors in the code, but I haven't used Autofac for a while.

这篇关于通过Autofac容器WPF用户控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆