2

I did not managed to find any similar example, so I decided to ask the question.

I am using Autofac to register my service layer interfaces and I am wondering, can I inject one into App.xaml.cs?

I am having my own log service, that I want to run in case of fatal error in the application.

As far as I know similar way you can inject dependency to the window, can I do it the same in App.xaml.cs?

public partial class App : Application
    {
        private readonly ILogService _log;

        public App()
        {

        }

        public App(ILogService log) : this()
        {
            _log = log;
        }

        async Task App_DispatcherUnhandledExceptionAsync(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            _log.Error("App.xaml.cs exception: " + e.Exception.Message);

            await _log.SaveAllLinesAsync();

            e.Handled = true;
        }
    }

Autofac IoC:

public class BootStrapper
    {
        /// <summary>
        /// IoC container
        /// </summary>
        /// <returns></returns>
        public static IContainer BootStrap()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<EventAggregator>()
              .As<IEventAggregator>().SingleInstance();

            builder.RegisterType<LogService>()
              .As<ILogService>().SingleInstance();

            builder.RegisterType<DeleteView>().AsSelf();
            builder.RegisterType<DeleteViewModel>().AsSelf().SingleInstance();
            builder.RegisterType<PhraseView>().AsSelf();
            builder.RegisterType<PhraseViewModel>().AsSelf().SingleInstance().WithParameter(new NamedParameter("searchPhrase", ""));
            builder.RegisterType<PopulateDictionaries>().AsSelf().SingleInstance();

            return builder.Build();
        }
    }

IoC initializing in ViewModelLocator:

public class ViewModelLocator
    {
        IContainer _container;
        public ViewModelLocator()
        {
            _container = BootStrapper.BootStrap();
        }

        //view models below
    }
bakunet
  • 51
  • 5
  • For places which are the first ones to load/execute, I would typically explicitly call my DepedencyContainer to Resolve any dependencies. Have you tried that out, instead of injecting from the constructor? – bit Aug 28 '19 at 04:24
  • This might help you : https://stackoverflow.com/questions/43689124/adding-autofac-to-wpf-mvvm-application – CharithJ Aug 28 '19 at 04:25
  • The problem is that you are trying to inject prior to the container being setup. Most DI frameworks require a one-time configuration of the container and that is usually at application start-up - the exact place where you have encountered this problem. –  Aug 28 '19 at 04:26
  • I didnt mention, that I have already IoC for registering my dependencies and views + VM (added code to the question). Right now code is compiling and throwing no exception. But I am not quite sure that DI constructor of `App.xaml.cs` will be used in case of not handled exception. And I need to use singleton of `LogService` in this class. – bakunet Aug 28 '19 at 04:33
  • WPF only has two different ways of startup I believe **1)** _purely via XAML_ with no App code-behind and **2)** with `App` _code-behind_. With the latter I can't see how you can inject `App(ILogService log)` when you haven't setup DI yet –  Aug 28 '19 at 04:47
  • @MickyD but I have second constructor with DI. – bakunet Aug 28 '19 at 05:00
  • If it's anything like Caliburn and Windsor, a `System.Windows.Application` has **already** been created **prior** to `BootStrapper` executing. I accomplished this with having a `BootStrapper` defined in my **App.xaml**'s `` –  Aug 28 '19 at 05:22
  • Yeah, I am affraid of this, that App.xaml.cs with DI constructor will be not used at all, and is created with default ctor; – bakunet Aug 28 '19 at 05:35
  • How do you set up your container? What is your app's entry point? Please show us where you call the `BootStrap` method. – dymanoid Aug 28 '19 at 09:06
  • @bakunet where are you initializing that bootstrapper? – Nkosi Aug 28 '19 at 11:52
  • I am initializing that bootstrapper in my `ViewModelLocator`, as in updated question. – bakunet Aug 28 '19 at 12:07

1 Answers1

0

If you want to inject the App class with a dependency, you should define a custom Main method where you instantiate the App class:

public class Program
{
    [STAThread]
    public static void Main(string[] args)
    {
        ILogService logService = ...;
        App app = new App(logService);
        app.InitializeComponent();
        app.Run();
    }
}

If you do this, remember to change the Build Action of App.xaml from ApplicationDefinition to Page.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • @bakunet: Did you try this or what happened? This is the way to inject the `App` class, contrary to what the downvoter apparently thinks :) – mm8 Aug 29 '19 at 12:32