Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Future WPF IoC Friendly #499

Open
TrabacchinLuigi opened this issue Apr 4, 2019 · 11 comments

Comments

@TrabacchinLuigi
Copy link

commented Apr 4, 2019

Something that i really miss on WPF is the ability to avoid using service locators and control how nested controls and pages are created, i'd really like to have some object injected in the UserControl constructors, and a way to tell WPF how to construct them (and maybe provide some mocks for the IDE), instead of the empty constructor.
Maybe since a lot is being rewritten to be core it is a good time to support IoC.
I'm aware that we can achieve something similar with MVVM but... it's not the same...

@stevenbrix stevenbrix added this to the Future milestone Apr 5, 2019

@stevenbrix

This comment has been minimized.

Copy link
Member

commented Apr 5, 2019

This sounds like an interesting idea, although I'm not exactly sure what you're trying to accomplish. Can you provide more information (like a code example) on what you are envisioning this to look like? How would the xaml parser know which constructor to call and with which parameters?

@TrabacchinLuigi

This comment has been minimized.

Copy link
Author

commented Apr 5, 2019

One of the best API i ever worked with is the one from asp.net core, so i'm inspiring from that.
I'm imagining that WPF would work just as it does now, but when it finds in the tree an object that does not have an empty constructor would instruct the user to change the default entry point with something that looks like this:

namespace WPFApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWPFBuilder(args).Build().Run();
        }

        public static IWPFBuilder CreateWPFBuilder(string[] args) 
        {
             // WPF.CreateDefaultBuilder(args); // here all the default way of constructing Controls, FrameworkElements 
             // WPF.CreateDefaultBuilder(args, (builder) => { /* Add custom registrations here, shared between IDE and runtime*/ });
             WPF.CreateDefaultBuilder(args, (ideBuilder, builder) => { /* Add custom registrations here*/ });
         }
    }
}

@hippieZhou

This comment has been minimized.

Copy link

commented Apr 5, 2019

Yeh,I think this will be a good feature for wpf with dotnetcore 3.0,I vote you.

@Valks

This comment has been minimized.

Copy link

commented May 10, 2019

I've thrown a preliminary (working) example together. It's bare bones but works surprisingly well.

Only issue is it has trouble shutting down. Not sure what's keeping the app alive.

https://github.com/Valks/DotnetCore.GenericHost.WPF.Demo

It would be nice to take it that step further as per @TrabacchinLuigi 's example but it isn't that bad as is.

@miloush

This comment has been minimized.

Copy link

commented May 10, 2019

@Valks Make sure your async stuff is running on a background thread, an app stays running as long as any non-background threads are running.

@Valks

This comment has been minimized.

Copy link

commented May 15, 2019

I needed to call _host.Dispose();. Seems it has a background thread or two (sample updated).

@stevenbrix

This comment has been minimized.

Copy link
Member

commented May 15, 2019

This is awesome, thank you for the discussion! Once we've formalized our API submission and review process, we'll be able to share that and then get the ball moving a bit. Just so we are on the same page, it's unlikely we'll be ready to accept these changes for .NET Core 3.0 RTM, but we should be able to look at them soon after. Thanks for the great contributions!

@grubioe grubioe added this to Incoming / New in Future Enhancements / Bugs May 15, 2019

@MeikTranel

This comment has been minimized.

Copy link

commented May 16, 2019

I have been exploring this in the Context of the Stylet MVVM Framework (https://github.com/canton7/Stylet - this library also exposes a similar thing called "BootStrapper" which is basically a more strictly typed version of an OWIN startup class). Build myself a similar construct that @Valks is showing in his sample. One issue that came up with using the ASP.NET IoC Extension Interfaces is the fact that it is pretty tightly coupled to the idea of PageLoads. Theres 3 types of lifecycles: Singleton, Scoped & Transient -> Singleton and Transient can be translated to the WPF use case no problem. Scoped i'm not sure. In ASP.NET Scoped means it creates an Object once per Connection (thus optimistically said per pageload). Whether this can be translated to Client Applications is questionable - and without using we'd lose alot of good pre-existing libraries building great extension method for ServiceCollection.

As for the greater picture:
When designing this i urge everyone to look at this from the MVVM viewpoint and less from UserControl UseCase. IoC is especially useful where pre-configuration has to be done. Its far more likely that ViewModels would gain from Dependency Injection automation than UserControls, because UserControls tend to pull in less side-effect rich dependencies.

@weltkante

This comment has been minimized.

Copy link

commented May 16, 2019

@MeikTranel Classically window lifetime is something which could be a good fit, in our application its pretty common requirement for services to have distinct instances for distinct windows. On the other hand there are lightweight windows which don't require a scope at all ("message box" style windows) or dialogs which want to inherit the scope from their invocing window.

Also I do understand that not everyone likes multi-window applications and some people prefer having different views, basically inlining the "window" scopes into the main window.

So at the end you have to allow the application programmer to decide where scope boundaries are, you can just try to give reasonable defaults to make the common cases easier.

@Lakritzator

This comment has been minimized.

Copy link

commented Sep 10, 2019

I would like to add my repository to this discussion, it contains multiple UI samples build on the generic host, including WPF: https://github.com/dapplo/Dapplo.Microsoft.Extensions.Hosting

It has samples with o.a.:

Besides there are services to prevent your application for being started multiple times and also something to load plugins.

The main challenge was to offload the UI onto its own thread, otherwise the background services got into problems. So I actually spent quite a lot of time to make the whole life-cycle work.

But the whole idea of using DI for a UI application makes sense, and it does feel very natural to me. The code is still very experimental, and the API probably needs improvement, but it can be used as a base to continue with.

Actually @onovotny also tweeted about using the generic host for UI, but I think he is to much occupied to react to my answers.

@laurentkempe

This comment has been minimized.

Copy link

commented Sep 11, 2019

I don't know about @onovotny tweet but I wrote a recent blog post "WPF and .NET Generic Host with .NET Core 3.0" which shows one solution which is working for me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
9 participants
You can’t perform that action at this time.