From 7326ff668415a64aede4c089e8224ce4bc6d9865 Mon Sep 17 00:00:00 2001 From: Holger Boerchers Date: Sun, 12 Aug 2018 13:23:44 +0200 Subject: [PATCH] Initial commit --- .vscode/launch.json | 28 ++++++++++++++++++++++++ .vscode/tasks.json | 15 +++++++++++++ Program.cs | 28 ++++++++++++++++++++++++ RegisteredType.cs | 17 +++++++++++++++ ServiceOne.cs | 22 +++++++++++++++++++ ServiceTwo.cs | 22 +++++++++++++++++++ SmallInjector.cs | 47 ++++++++++++++++++++++++++++++++++++++++ SmallInjectorDemo.csproj | 8 +++++++ SmallInjectorDemo.sln | 37 +++++++++++++++++++++++++++++++ UsefulClass.cs | 29 +++++++++++++++++++++++++ 10 files changed, 253 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 Program.cs create mode 100644 RegisteredType.cs create mode 100644 ServiceOne.cs create mode 100644 ServiceTwo.cs create mode 100644 SmallInjector.cs create mode 100644 SmallInjectorDemo.csproj create mode 100644 SmallInjectorDemo.sln create mode 100644 UsefulClass.cs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9724023 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/netcoreapp2.1/Playground.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ,] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2644cb2 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Playground.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..3490af5 --- /dev/null +++ b/Program.cs @@ -0,0 +1,28 @@ +using System; + +namespace Playground +{ + internal static class Program + { + private static void Main() + { + Console.WriteLine("Small dependency injection example."); + var injector = new SmallInjector(); + injector.RegisterType(true); + injector.RegisterType(true); + injector.RegisterType(false); + + Console.WriteLine(); + Console.WriteLine("Resolve class instances."); + var useful1 = injector.Resolve(); + var useful2 = injector.Resolve(); + var useful3 = injector.Resolve(); + Console.WriteLine(); + Console.WriteLine("Run test methods."); + useful1.TestTheServices(); + useful2.TestTheServices(); + useful3.TestTheServices(); + Console.ReadLine(); + } + } +} \ No newline at end of file diff --git a/RegisteredType.cs b/RegisteredType.cs new file mode 100644 index 0000000..b5cfbc6 --- /dev/null +++ b/RegisteredType.cs @@ -0,0 +1,17 @@ +using System; + +namespace Playground +{ + public class RegisteredType + { + public RegisteredType(Type concreteType, bool isSingleton) + { + ConcreteType = concreteType; + IsSingleton = isSingleton; + } + + public readonly bool IsSingleton; + public readonly Type ConcreteType; + public object SingletonInstance { get; set; } + } +} \ No newline at end of file diff --git a/ServiceOne.cs b/ServiceOne.cs new file mode 100644 index 0000000..547f16c --- /dev/null +++ b/ServiceOne.cs @@ -0,0 +1,22 @@ +using System; + +namespace Playground +{ + public class ServiceOne : IServiceOne + { + private readonly Guid _guid; + + public ServiceOne() + { + _guid = Guid.NewGuid(); + Console.WriteLine(nameof(ServiceOne) + ".ctor\t\tId: " + _guid); + } + + public override string ToString() => nameof(ServiceOne) + ".ToString()\tId: " + _guid; + } + + public interface IServiceOne + { + + } +} \ No newline at end of file diff --git a/ServiceTwo.cs b/ServiceTwo.cs new file mode 100644 index 0000000..19f1166 --- /dev/null +++ b/ServiceTwo.cs @@ -0,0 +1,22 @@ +using System; + +namespace Playground +{ + public class ServiceTwo : IServiceTwo + { + private readonly Guid _guid; + + public ServiceTwo() + { + _guid = Guid.NewGuid(); + Console.WriteLine(nameof(ServiceTwo) + ".ctor\t\tId: " + _guid); + } + + public override string ToString() => nameof(ServiceTwo) + ".ToString()\tId: " + _guid; + + } + + public interface IServiceTwo + { + } +} \ No newline at end of file diff --git a/SmallInjector.cs b/SmallInjector.cs new file mode 100644 index 0000000..b1efa84 --- /dev/null +++ b/SmallInjector.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +namespace Playground +{ + public class SmallInjector + { + private readonly Dictionary _container = new Dictionary(); + + public void RegisterType(bool isSingleton) + { + _container.Add(typeof(TInterface), new RegisteredType(typeof(TService), isSingleton)); + } + + public void RegisterType(bool isSingleton) => RegisterType(isSingleton); + + public TService Resolve() => (TService)Resolve(typeof(TService)); + + public object Resolve(Type serviceInterface) + { + if (!_container.TryGetValue(serviceInterface, out var registeredType)) + { + throw new Exception("Can't resolve dependency " + serviceInterface); + } + + if (registeredType.IsSingleton && registeredType.SingletonInstance != null) + return registeredType.SingletonInstance; + var constructor = registeredType.ConcreteType.GetConstructors()[0]; + var parameters = constructor.GetParameters(); + var constructorParameters = new object[parameters.Length]; + for (var i = 0; i < parameters.Length; i++) + { + constructorParameters[i] = Resolve(parameters[i].ParameterType); + } + + if (registeredType.IsSingleton) + { + return registeredType.SingletonInstance ?? (registeredType.SingletonInstance = constructor.Invoke(constructorParameters)); + } + return constructor.Invoke(constructorParameters); + + } + } +} \ No newline at end of file diff --git a/SmallInjectorDemo.csproj b/SmallInjectorDemo.csproj new file mode 100644 index 0000000..b30d547 --- /dev/null +++ b/SmallInjectorDemo.csproj @@ -0,0 +1,8 @@ + + + Exe + netcoreapp2.1 + SmallInjectorDemo + SmallInjectorDemo + + \ No newline at end of file diff --git a/SmallInjectorDemo.sln b/SmallInjectorDemo.sln new file mode 100644 index 0000000..c2d049d --- /dev/null +++ b/SmallInjectorDemo.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SmallInjectorDemo", "SmallInjectorDemo.csproj", "{620CC001-7DF9-4233-AFC2-187FD9144835}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|Any CPU.Build.0 = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|x64.ActiveCfg = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|x64.Build.0 = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|x86.ActiveCfg = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Debug|x86.Build.0 = Debug|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|Any CPU.ActiveCfg = Release|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|Any CPU.Build.0 = Release|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|x64.ActiveCfg = Release|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|x64.Build.0 = Release|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|x86.ActiveCfg = Release|Any CPU + {620CC001-7DF9-4233-AFC2-187FD9144835}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1A146B09-F1B0-4A1E-B396-739788B6A68E} + EndGlobalSection +EndGlobal diff --git a/UsefulClass.cs b/UsefulClass.cs new file mode 100644 index 0000000..b5520a6 --- /dev/null +++ b/UsefulClass.cs @@ -0,0 +1,29 @@ +using System; + +namespace Playground +{ + public class UsefulClass + { + private readonly IServiceOne _service; + private readonly IServiceTwo _service2; + private readonly Guid _guid; + + public UsefulClass(IServiceOne service, IServiceTwo service2) + { + _service = service; + _service2 = service2; + _guid = Guid.NewGuid(); + Console.WriteLine(nameof(UsefulClass) + ".ctor\tId: " + _guid); + } + + public void TestTheServices() + { + Console.WriteLine(ToString()); + Console.WriteLine(_service.ToString()); + Console.WriteLine(_service2.ToString()); + } + + public override string ToString() => nameof(UsefulClass) + ".ToString()\tId: " + _guid; + + } +} \ No newline at end of file