Is Dependency Injection possible with a WPF application?

前端 未结 8 1002
忘了有多久
忘了有多久 2021-01-30 21:05

I want to start using dependency injection in my WPF application, largely for better unit testability. My app is mostly constructed along the M-V-VM pattern. I\'m looking at Aut

相关标签:
8条回答
  • 2021-01-30 21:57

    We are experiencing a similar issue. We are looking forward for a solution that will provide Design time support under Expression Blend 2.0 (Strong Type). Plus we are looking forward for a solution to have some Mock+Auto-Generated data sample available under Expression Blend.

    Of course, we are looking also to have all those thing work using an IOC pattern.

    Paul Stovell as an interesting article to start with: http://www.paulstovell.com/blog/wpf-dependency-injection-in-xaml

    So I try a couple thing to add more valuable design time support for Binding and mocking object at Design time, right now I’m having most of my problem related to get a strong typed connection made between the View (code) to the ModelView(Xaml), I tried a couple scenario:

    Solution 1 : Using Generic to create the View

    public class MyDotNetcomponent<T> : SomeDotNetcomponent 
    {
        // Inversion of Control Loader…
        // Next step add the Inversion of control manager plus
        // some MockObject feature to work under design time
        public T View {Get;}
    }
    

    This solution does not work since Blend does not support Generic inside is design surface but Xaml do have some, well work at runtime but not at design;

    Solution 2: ObjectDataProvider

    <ObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
    <!-- Work in Blend -->
    <!—- IOC Issue: we need to use a concrete type and/or static Method there no way to achive a load on demande feature in a easy way -->
    

    Solution 3: Inherit ObjectDataProvider

    <CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView}" />
    <!-- Cannot inherit from ObjectDataProvider to achive the right behavior everything is private-->
    

    Solution 4: Create a mock ObjectDataProvider from scratch to the job

    <CWD:ServiceObjectDataProvider ObjectType="{x:Type CP:IFooView }" />
    <!-- Not working in Blend, quite obvious-->
    

    Solution 5: Create a Markup Extension (Paul Stovell)

    <CWM:ServiceMarkup MetaView="{x:Type CP:IFooView}"/>
    <!-- Not working in Blend -->
    

    Just to clear one point. When I said “not working in blend”, I mean that the Binding dialog is not usable and the designer needs to handwrite the XAML by itself.

    Our next step will probably be to take the time to evaluate the ability to create a plug-in for Expression Blend.

    0 讨论(0)
  • 2021-01-30 22:00

    I think you've hit on the issue. The controls need to be injected into their parent rather than created declaratively through XAML.

    For DI to work, a DI container should create the class that is accepting dependencies. This means that the parent will not have any instances of the child controls at design time and look something like a shell in the designer. This is probably the recommended approach.

    The other "alternative" is to have a global static container called from the control's constructor, or something similar. There is a common pattern in which two constructors are declared, one with a parameter list for constructor injection and the other without parameters that delegates:

    // For WPF
    public Foo() : this(Global.Container.Resolve&lt;IBar&gt;()) {}
    
    // For the rest of the world
    public Foo(IBar bar) { .. }
    

    I would almost call this an antipattern but for the fact that some frameworks leave no other choice.

    I'm not even half an expert in WPF, so I'm expecting a healthy serving of downmod here :) but hope this helps. The Autofac group (linked from the homepage) might be another place to ask this question. The Prism or MEF sample apps (which include some WPF examples) should give you an idea of what is possible.

    0 讨论(0)
提交回复
热议问题