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