Skip to content

jwdeveloper/JW.Injection

Repository files navigation

JW.Injection

The goal of creating this project was to learn how a dependency injection container works under the hood.

🤔 What is dependecy injection?

Dependency injection is a design pattern that is used to deliver needed dependency into a class constructor you can read more about it up here

🤔 What is dependecy injection container?

To escape from the tedious job of creating the objects instances and putting them into the constructor, a group of the wise people came up with the idea to automize the whole process by creating API library where you just need to register the class type into Container and then just get it. Object with all of its dependencies will be instantiated automatically. Here are some of the most popluar libraris

Microsoft.DependencyInjection

Autofac

UnityContainer

Down below is my implementation and I strongly encourage you to look into the code and explore how the whole thing works 😀

Usage

//Transient means Instance of class will be created time new
//Singleton means Instance will be created once

builder.RegisterTransient<IGame, Game>();
builder.RegisterTransient<IPlayer, Player>();
builder.RegisterTransient<IPlayerStats, PlayerStats>();
//In case you need to specify out coming object instance use lamda
builder.RegisterSingleton<GameSettings>(() =>
{
    var filePath = @"C:\folder\settings.json";
    return new GameSettings(filePath);
});

var container = builder.Build();
var game = container.Find<IGame>();
game.DisplayObjects();

Output

Hash code is basically Id of the object
=================================================
Created -> GameSettings  Hash Code: 23458411
Created -> PlayerStats  Hash Code: 21083178
Created -> Player  Hash Code: 55530882
Created -> PlayerStats  Hash Code: 30015890
Created -> Player  Hash Code: 1707556
Created -> Game  Hash Code: 15368010

=========        Objects hash codes     =========
Game 15368010
Player1 55530882
Player1.PlayerStats 21083178
Player1.GameSettings 23458411
Player2 1707556
Player2.PlayerStats 30015890
Player2.GameSettings 23458411
GameSettings 23458411
=================================================

Example classes

Game

public interface IGame
{
    public void DisplayObjects();
}

public class Game : IGame
{
    private readonly IPlayer _player1;
    private readonly IPlayer _player2;
    private readonly GameSettings _gameSettings;

    public Game(IPlayer player1, IPlayer player2, GameSettings gameSettings)
    {
        _player1 = player1;
        _player2 = player2;
        _gameSettings = gameSettings;
        Console.WriteLine($"Created -> {GetType()}  Hash Code: {GetHashCode()}");
    }

    public void DisplayObjects()
    {
        //hashcode is basically id of the object
        Console.WriteLine("========= Objects hash codes ==========");
        Console.WriteLine($"Game {GetHashCode()}");
        _player1.DisplayObjects("Player1");
        _player2.DisplayObjects("Player2");
        Console.WriteLine($"GameSettings {_gameSettings.GetHashCode()}");
        Console.WriteLine("=======================================");
    }
}

Player

public interface IPlayer
{
    public void DisplayObjects(string playerName);
}

public class Player : IPlayer
{
    private readonly string name;
    private readonly GameSettings _gameSettings;
    private readonly IPlayerStats _playerStats;

    public Player(string name) : this(new GameSettings("settings.json"), new PlayerStats())
    {
        this.name = name;
    }

    //By the default first constructor is injected therefore
    //in case you have more then one constructor use attribute 'Inject' to mark constructor for injection
    [Inject]
    public Player(GameSettings gameSettings, IPlayerStats playerStats)
    {
        _gameSettings = gameSettings;
        _playerStats = playerStats;
        Console.WriteLine($"Created -> {GetType()}  Hash Code: {GetHashCode()}");
    }

    public void DisplayObjects(string playerName)
    {
        Console.WriteLine($"{playerName} {GetHashCode()}");
        Console.WriteLine($"{playerName}.PlayerStats {_playerStats.GetHashCode()}");
        Console.WriteLine($"{playerName}.GameSettings {_gameSettings.GetHashCode()}");
    }
}

PlayerStats

public interface IPlayerStats
{
}

public class PlayerStats : IPlayerStats
{
    public PlayerStats()
    {
        Console.WriteLine($"Created -> {GetType()}  Hash Code: {GetHashCode()}");
    }
}

GameSettings

public class GameSettings
{
    private readonly string _filePath;
    public GameSettings(string filePath)
    {
        _filePath = filePath;
        Console.WriteLine($"Created -> {GetType()}  Hash Code: {GetHashCode()}");
    }
}