Dependency Injection is een krachtige techniek om je applicatie naar een hoger niveau te tillen. Door abstracties te gebruiken in plaats van concrete implementaties, maak je je applicatie flexibeler en eenvoudiger te beheren. Een ontwerpprincipe dat hierbij hoort, is Dependency Inversion, waarbij hogere niveaus afhankelijk zijn van abstracties en beide niveaus afhankelijk zijn van elkaar. In deze blog leg ik uit hoe je Autofac kunt gebruiken om Dependency Injection te implementeren in een .NET Framework Console Application. We doorlopen de volgende stappen:
Stap 1: Opzetten van een .NET Framework Console Application
Begin met het opzetten van een .NET Framework Console Application. Maak een App
-klasse aan met een Run
-methode. We zullen Dependency Injection toepassen via de constructor. Omdat Program.Main
een statische klasse is zonder constructor, kunnen we de App
-klasse niet direct vanuit Program.Main
gebruiken. Maak daarom een instantie van App
aan in de Main
-methode en roep vervolgens de Run
-methode aan. De Run
-methode is waar je je algemene code zult schrijven.
class Program
{
static void Main(string[] args)
{
App app = new App();
app.Run();
Console.ReadLine();
}
}
public class App
{
public void Run()
{
// Algemene code hier
}
}
Stap 2: Implementeren van een te injecteren klasse
Maak een klasse aan die je wilt injecteren in de App
-klasse. In dit voorbeeld noem ik de klasse Repository
. Definieer enkele eigenschappen en een methode binnen de Repository
-klasse. Laat Repository
de interface IRepository
implementeren, die dezelfde eigenschappen en methode bevat. Hoewel het gebruik van een interface niet verplicht is voor Dependency Injection, wordt het wel aanbevolen. In de Write
-methode van Repository
schrijven we iets naar de console voor testdoeleinden. Maak nu een instantie van Repository
in de App
-klasse en roep de Write
-methode aan. Start je applicatie om te bevestigen dat alles werkt. Je zou ‘Writing…’ in de console moeten zien verschijnen.
public class Repository : IRepository
{
public string Name { get; set; }
public string Version { get; set; }
public void Write()
{
Console.WriteLine(“Writing…”);
}
}
public interface IRepository
{
string Name { get; set; }
string Version { get; set; }
void Write();
}
Stap 3: Implementeren van Dependency Injection met Autofac
Om de concrete implementaties in je applicatie te verminderen, kun je Dependency Injection toepassen. Een goede manier om dit te doen is met behulp van Autofac. Installeer Autofac via NuGet en maak vervolgens een statische klasse AutofacConfig
aan met daarin een statische Configure
-methode. In deze methode bouwen we de container op die de klassen zal injecteren. Maak een instantie van ContainerBuilder
uit de Autofac namespace aan. Roep vervolgens de RegisterType
-methode van de builder aan voor het type App
. Voor de Repository
-klasse doen we hetzelfde, maar we koppelen deze aan de interface IRepository
met behulp van de As
-methode. Tot slot retourneren we het resultaat van de Build
-methode.
public static class AutofacConfig
{
public static IContainer Configure()
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<App>();
builder.RegisterType<Repository>().As<IRepository>();
return builder.Build();
}
}
Ga nu terug naar Program.Main
en maak een instantie van IContainer
door de Configure
-methode van AutofacConfig
aan te roepen. Direct daaronder maak je een scope aan met behulp van container.BeginLifetimeScope()
. Deze scope zal worden gebruikt voor Dependency Injection. Om de App
-klasse uit de container te halen in plaats van een concrete implementatie, roep je de Resolve
-methode van de scope aan met als type App
om een instantie op te halen.
class Program
{
static void Main(string[] args)
{
IContainer container = AutofacConfig.Configure();
ILifetimeScope scope = container.BeginLifetimeScope();
App app = scope.Resolve<App>();
app.Run();
Console.ReadLine();
}
}
Stap 4: Dependency Injection toepassen
Nu is het tijd om een instantie van Repository
in de App
-klasse te injecteren. We zullen de bestaande instantie van Repository
initialiseren vanuit de constructor, omdat deze daar wordt geïnjecteerd. Voeg een constructor toe aan de App
-klasse met een parameter van het type IRepository
. Maak ook een veld van het type IRepository
aan binnen App
en vul deze in de constructor met de geïnjecteerde Repository
. Nu kun je in de Run
-methode de Write
-methode van Repository
aanroepen. Wanneer je de applicatie uitvoert, zou je hetzelfde resultaat moeten zien als voorheen.
public class App
{
private readonly IRepository _repository;
public App(IRepository repository)
{
_repository = repository;
}
public void Run()
{
_repository.Write();
}
}
Hoewel Dependency Injection aanvankelijk wat extra tijd kost om op te zetten, is het de moeite waard, vooral bij grotere applicaties. Je zult snel de voordelen ervan ervaren, vooral wanneer je bijvoorbeeld Unit Testing toepast, waarbij het eenvoudig wordt om mockklassen door je hele applicatie te injecteren.
Dependency Injection is een krachtig concept dat je applicatie flexibeler, testbaarder en eenvoudiger te onderhouden maakt.
Meer weten over onze oplossingen?
Onze consultants hebben veel ervaring binnen een grote verscheidenheid aan branches.
Eens verder brainstormen over de mogelijkheden voor jouw organisatie?
Maak kennis met onze specialist Arnoud van der Heiden.