[C#][Uno Platform] Create desktop applications on Ubuntu 2
Tags: csharp, unoplatform, ubuntu
Published: 2022-01-02 10:33:52

## Intro
* [[C#][Uno Platform] Create desktop applications on Ubuntu 1](https://dev.to/masanori_msl/cuno-platform-create-desktop-applications-on-ubuntu-1-3o3i)
* [[.NET 6][Uno Platform][Ubuntu 21.10] Using Leap Motion](https://dev.to/masanori_msl/net-6uno-platformubuntu-2110-using-leap-motion-5a5n)

This time, I will try installing NuGet packages, using DI, firing life-cycle events.

### Environments

* Ubuntu ver.21.10
* .NET ver.6.0.101
* Uno Platform ver.4.0.11

## Installing NuGet packages

To log, using DI, etc., I want to install NuGet packages.
When I install packages by NuGet Package Manager, I have to select the target project.

* [NuGet Package Manager - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=jmrog.vscode-nuget-package-manager)

To use the packages in all projects, I have to install into "UnoSolutionTemplate.net6.csproj".

If the package is only for specific platform, I have to add in specific projects.

## Life-cycle events

Sometimes, I want to execute something on loading the page, closing the page, and so on.

### Shared project

In "UnoSample.Shared", I can use "Loaded" event in MainPage.xaml.cs to execute on the page loaded.

#### MainPage.xaml.cs
```cs
using Windows.UI.Xaml.Controls;
using UnoSample.ViewModels;

namespace UnoSample
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.Loaded += (sender, e) => Console.WriteLine("Loaddeded");
            this.InitializeComponent();
            this.DataContext = new MainPageViewModel();
        }
    }
}
```

How about closing applications event?
I can't find any events what are called on closing.

So I think I shall use closing events in every specific platform projects.
For example, WPF can use "OnClosing" and "OnClosed" methods.

### Executing on closing

When I open MainPage, these classes are instantiated in sequence.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsvaddmqfz62ox67s4ih.png)

In "UnoSample.Skia.Gtk" project, there is only "Main" method.
So I can execute closing operations after "host.Run()".

#### Program.cs
```cs
using GLib;
using Uno.UI.Runtime.Skia;
using UnoSample.Skia.Gtk.MotionControllers;

namespace UnoSample.Skia.Gtk
{
	class Program
	{
		static void Main(string[] args)
		{
			// I also can use "using statement"
			using(var motionController = new MotionController())
			{
				ExceptionManager.UnhandledException += delegate (UnhandledExceptionArgs expArgs)
				{
					expArgs.ExitApplication = true;
				};
				var host = new GtkHost(() => new App(), args);
				host.Run();
				// execute closing operations.
			}
		}
	}
}
```
### Call methods in UnoSample.Shared classes

How shall I call methods in UnoSample.Shared classes?

I can access App.xaml.cs like below.

#### App.xaml.cs
```cs
...
namespace UnoSample
{
    public sealed partial class App : Application
    {
        private Window _window;
        public void Greet(string message)
        {
            Console.WriteLine($"SharedApp {message}");
        }
...
```

#### Program.cs
```cs
...
	class Program
	{
		static void Main(string[] args)
		{
			using(var motionController = new MotionController())
			{
...
				var host = new GtkHost(() => new App(), args);
				host.Run();
				// Because I can't get instances by "App.Current" before executing "host.Run()",
				// I can only execute closing operations from Program.cs. 
				((App)App.Current).Greet("Call from Gtk");
			}
		}
	}
}
```

* [MVVM and Dependency Injection in Uno Platform - Andrew Hoefling](https://www.andrewhoefling.com/Blog/Post/mvvm-and-dependency-injection-in-uno-platform-ios-android-wasm-uwp)

## DI (Dependency Injection)
Because I want to avoid the classes are coupled tightly, I try using DI framework.
In this time, I tried using "Microsoft.Extensions.DependencyInjection(ver.6.0.0)"

* [【.NET 5】【WPF】【ClosedXML】Draw and print spreadsheets 1](https://dev.to/masanori_msl/net-5-wpf-closedxml-draw-and-print-spreadsheets-1-16g6)

Because I couldn't find the way to inject View and their code behinds, I put IServiceProvider into App.xaml.cs of the shared project and get injected instances from it.

#### Program.cs
```cs
using GLib;
using Microsoft.Extensions.DependencyInjection;
using Uno.UI.Runtime.Skia;
using UnoSample.ViewModels;

namespace UnoSample.Skia.Gtk
{
	class Program
	{
		static void Main(string[] args)
		{
			var servicesProvider = BuildDi(args);
            using (servicesProvider as IDisposable)
			{
...
				var host = new GtkHost(() => new App(servicesProvider), args);
				host.Run();
			}
		}
		private static IServiceProvider BuildDi(string[] args)
        {
            var services = new ServiceCollection();
            services.AddScoped<MainPageViewModel>();
            return services.BuildServiceProvider();
        }
	}
}
```

#### App.xaml.cs
```cs
...
namespace UnoSample
{
    public sealed partial class App : Application
    {
        private Window? _window;
        public IServiceProvider ServiceProvider { get; }

        public App(IServiceProvider serviceProvider)
        {
            this.ServiceProvider = serviceProvider;
            InitializeLogging();

            this.InitializeComponent();
...
```

#### MainPage.xaml.cs
```cs
using Windows.UI.Xaml.Controls;
using UnoSample.ViewModels;

namespace UnoSample
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.DataContext = ((App)App.Current).ServiceProvider.GetService(typeof(MainPageViewModel));
        }
    }
}
```

I'm not sure if this is the best method. 
Maybe it's better to use another DI framework。

If I will find more better one, I will edit this post or write new post.