gif gif

The interesting corner

gif gif

C# .NET notes

litedb embedded database -> document database objecten kunnen direct in db gezet worden

coordinator context -> entity relation -> object omzetten naar relationele db items

system.reactive -> observables -> één grote observable stream

dependency injection (Dependency injection - .NET | Microsoft Learn) Design Patterns Explained – Dependency Injection with Code Examples (stackify.com)
geregistreerd in lokale container
IServiceCollection registreert alle componenten in een systeem
dependencies in constructor zijn altijd verplicht

Dependency injection is a programming technique that makes a class independent of its dependencies. It achieves that by decoupling the usage of an object from its creation. You can introduce interfaces to break the dependencies between higher and lower level classes. If you do that, both classes depend on the interface and no longer on each other. link](https://stackify.com/dependency-injection/#:~:text=Dependency%20injection%20is%20a%20programming,inversion%20and%20single%20responsibility%20principles.)).

Dependency inversion SOLID Design Principles Explained: Dependency Inversion Principle with Code Examples (stackify.com)
High-level modules, which provide complex logic, should be easily reusable and unaffected by changes in low-level modules, which provide utility features.

  1. High-level modules should not depend on low-level modules. Both should depend on abstractions.
  2. Abstractions should not depend on details. Details should depend on abstractions.

extension methods Extension Methods - C# Programming Guide - C# | Microsoft Learn Shared -> alle onderdelen die andere modules gebruiken
transient -> elke keer een nieuwe als je hem opnieuw aanroept (in een web app voor iedere user opnieuw, voor de aparte users als singleton)
te herkennen door this
interfaces kunnen daarmee uitgebreid worden
Functionaliteit van klassen kan uitgebreid worden
Kan alleen als static methods in een static class
An extension method will never be called if it has the same signature as a method defined in the type.
When to use:

- when the original source isn't under your control
    - derived object is inappropriate or impossible
    - functionality shouldn't be expoed beyond its applicable scope
    

Hosted services .NET Hosted Service: Run a background service and task (uses .NET Core) (youtube.com)

Open/Closed principle (link](https://stackify.com/solid-design-open-closed-principle/)))

“Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. A class is closed, since it may be compiled, stored in a library, baselined, and used by client classes. But it is also open, since any new class may use it as parent, adding new features. When a descendant class is defined, there is no need to change the original or to disturb its clients”

Alles met repository is database code

Dependencies automatisch toegepast mits ze in Startup.cs zijn geregistreerd

communicatie met CM api is in Shared gedefinieerd

asynchroon is heel gebruikelijk in C#
Task<subtype>
cancellation token: een async operatie kan netjes afgesloten worden
Mediator
soort event bus maar dan op hoger niveau

ServiceHostProcess om windows service snel op te laten starten host het dotnet proces restart het dotnet proces als het crasht

gRPC

Introduction to gRPC

Authentication kan gebruikt worden (volgens Authentication and authorization in gRPC for ASP.NET Core | Microsoft Learn) door [Authorize] te gebruiken boven een functie

xUnit testing

Writing tests in .NET using xUnit

Aparte class in test file -> elke testfunctie gebruikt zijn eigen instance van die class

[Theory] kan gebruikt worden om meerdere sets data voor 1 test te testen
Voorbeeld:

[Theory]
[InlineData(13,5,8)]
[InlineData(0,3,-3)]
[InlineData(100,45,55)]
[InlineData(0,0,0)]
public void addTwoNumbers(int expected, int first, int second)
{
	Assert.Equal(expected, first + second);
}

Je kan een test skippen met [Fact(Skip = "reason for skip")]

met een params parameter aan een testfunctie kun je oneindig veel parameters toevoegen. Hiervoor moet je [MemberData(nameof(FunctionWithData))]. Hierbij returnt FunctionWithdata een IENumerable.
Je kan ook een class gebruiken, deze moet dan IEnumerable<object[]> extenden. Hiervoor moet je de bovengenoemde MemberData veranderen naar ClassData(typeof(ClassToUse)).

Als je niet alle testen dezelfde instance wil laten gebruiken, moet je een nieuwe class maken genaamd CollectionBehaviorOverride.cs met daarin:

using Xunit;

[assembly: CollectionBehavior(DisableTestParallelization = true)]
          

Collections

groepeer verschillende tests in aparte collections -> meerdere testen uitvoeren in dezelfde context

Als je dingen naar de console wil printen kan je een ITestOutputHelper toevoegen aan de fields van de test class en deze in de constructor meegeven (dependency injection doet de rest)

Om dezelfde context voor verschillende testen te gebruiken, moet de test class de IClassFixture<ClassUnderTest> extenden. Je moet dan een field van ClassUnderTest toevoegen aan de test class. Dit field moet ook in de constructor van de testclass.

XUnit heeft geen setup en teardown, alle initialization gebeurt in de constructor van de test class. Alle disposal gebeurt in de Dispose method. Hiervoor moet de testclass wel de IDisposable interface implementeren.

same context in multiple definitions

Maak een class die de ICollectionFixture<ClassUnderTest> implementeert. Voorbeeld:
[CollectionDefinition("name of collection")]
pulic class ClassDefinition : ICollectionFixture<ClassUnderTest>
{
	// all classes under this definition will use the same context
}

[Collection("name of collection")]
public class TestOne {}