Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lawrence_shaun_introducing_net_maui_build_and_deploy_crosspl.pdf
Скачиваний:
46
Добавлен:
26.06.2023
Размер:
5.15 Mб
Скачать

Chapter 3 The Fundamentals of .NET MAUI

Where ToBegin?

.NET MAUI applications have a single main entry point that is common across all platforms. This provides us with a way to centralize much of the initialization process for our applications and therefore only write it once.

You will have noticed that in each of the platform-specific main entry points covered in the previous section they all called MauiProgram. CreateMauiApp();. This is the main entry point into your .NET MAUI and shared application.

The CreateMauiApp method allows you to bootstrap your application. Bootstrapping refers to a self-starting process that is supposed to continue or grow without external input (Wikipedia quote). This means that

your implementation in this method is responsible for configuring the application from setting up logging, general application configuration, and registering implementations to be handled with dependency injection. This is one of the big improvements in .NET MAUI over Xamarin.Forms. This is done through the Generic Host Builder.

Generic Host Builder

I mentioned back in Chapter 1 that one of the benefits that comes with the evolution to .NET MAUI is powerful dependency injection. The Generic Host Builder is tried and tested through other .NET frameworks such as ASP .NET Core and it has thankfully become available to all application types now.

Before we jump in to how the Generic Host Builder works, let’s look at what exactly dependency injection is and why you should use it.

56

Chapter 3 The Fundamentals of .NET MAUI

What Is Dependency Injection?

Dependency injection (DI) is a software design pattern aimed at reducing hard-coded dependencies in a software application. A dependency is

an object that another object depends on. This hard-coded dependency approach is referred to as being tightly coupled. Let’s work through an example to show how and why it’s named so and how you can remove the need for the hard-coded dependencies thus making your design loosely coupled.

So, my wife is a fantastic baker. She bakes these beautiful, delicious cakes and this is the main reason I have gained so much weight recently. I am going to use the process of her baking a cake to show this concept of dependencies.

public class Baker

{

public Cake Bake()

{

}

}

The above code looks relatively straightforward, right? She bakes a cake. Now let’s consider how she might go about making the cake. She needs a way of sourcing the ingredients, weighing them, mixing them, and finally baking them. We end up with something like

public class Baker

{

private readonly WeighingScale weighingScale = new WeighingScale();

private readonly Oven oven = new Oven();

private readonly MixingMachine mixingMachine = new MixingMachine();

57

Chapter 3 The Fundamentals of .NET MAUI

private readonly IngredientsProvider ingredientsProvider = new IngredientsProvider();

public Cake Bake()

{

Ingredient ingredient = ingredientsProvider.Provide();

weighingScale.Weigh(ingredient);

}

}

We can see that for the Baker to do their job, they need to know about all these different pieces of equipment. Now imagine that the

WeighingScale breaks, and a replacement is provided. Baker will still need to weigh the ingredients but won’t care how that weighing is performed. Imagine that the new WeighingScale is digital and now requires batteries. There are a few reasons why we want to move away from having hard-­ coded dependencies as in our Baker example.

•\

If we did replace the WeighingScale with a different

 

implementation, we would have to modify the

 

Baker class.

•\

If the WeighingScale has dependencies (e.g., batteries

 

in our new digital scale), they must also be configured

 

in the Baker class.

•\

This becomes more difficult to unit test because the

 

Baker is creating dependencies and therefore a unit test

 

would result in having to test far more than a unit test is

 

designed to.

Dependency injection can help us to address the above issues by allowing us to achieve Inversion of Control (IoC). Inversion of Control essentially means that we are inverting the knowledge of the dependency

58

Chapter 3 The Fundamentals of .NET MAUI

from the Baker knowing about a WeighingScale to them knowing about something that can weigh ingredients but not an actual implementation. This is done through the introduction of an interface which we will call

IWeighingScale.

public class Baker

{

private readonly IWeighingScale weighingScale; private readonly Oven oven = new Oven();

private readonly MixingMachine mixingMachine = new MixingMachine();

private readonly IngredientsProvider ingredientsProvider = new IngredientsProvider();

public Baker(

IWeighingScale weighingScale)

{

this.weighingScale = weighingScale;

}

public Cake Bake()

{

Ingredient ingredient = ingredientsProvider.Provide();

this.weighingScale.Weigh(ingredient);

}

}

Now our Baker knows about an interface for something that can weigh their ingredients but not the actual thing that does the weighing. This means that in the scenario where the weighing scale breaks and a new one is supplied, there is no change to the Baker class in order to handle this new scale. Instead, it is registered as part of the application start-up

59