├── .gitignore
├── src
└── Nano.DependencyInjector
│ ├── ScopedAttribute.cs
│ ├── SingletonAttribute.cs
│ ├── TransientAttribute.cs
│ ├── InjectAttribute.cs
│ ├── DependencyInjectionServiceType.cs
│ ├── Nano.DependencyInjector.csproj
│ ├── ListExtension.cs
│ ├── DependencyInjectionConfigure.cs
│ └── NanoDependencyInjectorExtensions.cs
├── tests
├── Nano.APIExample
│ ├── Services
│ │ ├── IScopedTestService.cs
│ │ ├── ISingletonTestService.cs
│ │ ├── ITransientTestService.cs
│ │ └── Implementations
│ │ │ ├── ScopedTestService.cs
│ │ │ ├── SingletonTestService.cs
│ │ │ └── TransientTestService.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── Nano.APIExample.csproj
│ ├── WeatherForecast.cs
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Controllers
│ │ ├── TestController.cs
│ │ └── WeatherForecastController.cs
│ └── Startup.cs
└── Nano.DependencyInjector.Tests
│ ├── Nano.DependencyInjector.Tests.csproj
│ └── ListExtensionTests.cs
├── .github
└── workflows
│ └── main.yml
├── Nano.DependencyInjector.sln
└── Readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | /packages/
4 | riderModule.iml
5 | /_ReSharper.Caches/
6 | .idea/
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/ScopedAttribute.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable CheckNamespace
2 | using System;
3 |
4 | public class ScopedAttribute : Attribute
5 | {
6 | }
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/SingletonAttribute.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable CheckNamespace
2 | using System;
3 |
4 | public class SingletonAttribute : Attribute
5 | {
6 | }
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/TransientAttribute.cs:
--------------------------------------------------------------------------------
1 | // ReSharper disable CheckNamespace
2 | using System;
3 |
4 | public class TransientAttribute : Attribute
5 | {
6 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/IScopedTestService.cs:
--------------------------------------------------------------------------------
1 | namespace Nano.APIExample.Services
2 | {
3 | public interface IScopedTestService
4 | {
5 | string Test();
6 | }
7 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/ISingletonTestService.cs:
--------------------------------------------------------------------------------
1 | namespace Nano.APIExample.Services
2 | {
3 | public interface ISingletonTestService
4 | {
5 | string Test();
6 | }
7 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/ITransientTestService.cs:
--------------------------------------------------------------------------------
1 | namespace Nano.APIExample.Services
2 | {
3 | public interface ITransientTestService
4 | {
5 | string Test();
6 | }
7 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tests/Nano.APIExample/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/InjectAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Nano.DependencyInjector
6 | {
7 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
8 | public class InjectAttribute : Attribute
9 | {
10 |
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Nano.APIExample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/tests/Nano.APIExample/WeatherForecast.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Nano.APIExample
4 | {
5 | public class WeatherForecast
6 | {
7 | public DateTime Date { get; set; }
8 |
9 | public int TemperatureC { get; set; }
10 |
11 | public int TemperatureF => 32 + (int) (TemperatureC / 0.5556);
12 |
13 | public string Summary { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/DependencyInjectionServiceType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Extensions.DependencyInjection;
3 |
4 | namespace Nano.DependencyInjector
5 | {
6 | internal class DependencyInjectionServiceType
7 | {
8 | public Type ImplementationType { get; set; }
9 | public Type InterfaceType { get; set; }
10 | public ServiceLifetime LifeTime { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/Implementations/ScopedTestService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Nano.APIExample.Services.Implementations
4 | {
5 | [Scoped]
6 | public class ScopedTestService : IScopedTestService
7 | {
8 | public ScopedTestService()
9 | {
10 | Console.WriteLine("Created scoped instance");
11 | }
12 |
13 | public string Test()
14 | {
15 | return "Scoped";
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/Implementations/SingletonTestService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Nano.APIExample.Services.Implementations
4 | {
5 | [Singleton]
6 | public class SingletonTestService : ISingletonTestService
7 | {
8 | public SingletonTestService()
9 | {
10 | Console.WriteLine("Created singleton instance");
11 | }
12 |
13 | public string Test()
14 | {
15 | return "Singleton";
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Services/Implementations/TransientTestService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Nano.APIExample.Services.Implementations
4 | {
5 | [Transient]
6 | public class TransientTestService : ITransientTestService
7 | {
8 | public TransientTestService()
9 | {
10 | Console.WriteLine("Created transient instance");
11 | }
12 |
13 | public string Test()
14 | {
15 | return "Transient";
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Hosting;
6 | using Microsoft.Extensions.Configuration;
7 | using Microsoft.Extensions.Hosting;
8 | using Microsoft.Extensions.Logging;
9 |
10 | namespace Nano.APIExample
11 | {
12 | public class Program
13 | {
14 | public static void Main(string[] args)
15 | {
16 | CreateHostBuilder(args).Build().Run();
17 | }
18 |
19 | public static IHostBuilder CreateHostBuilder(string[] args) =>
20 | Host.CreateDefaultBuilder(args)
21 | .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
22 | }
23 | }
--------------------------------------------------------------------------------
/tests/Nano.DependencyInjector.Tests/Nano.DependencyInjector.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tests/Nano.DependencyInjector.Tests/ListExtensionTests.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Xunit;
3 |
4 | namespace Nano.DependencyInjector.Tests
5 | {
6 | public class ListExtensionTests
7 | {
8 | [Fact]
9 | public void TrueFunc_Should_Get_Items_When_Statement_Is_True()
10 | {
11 | var falseHeroes = new List();
12 | var heroes = new List() {"Conan", "Spawn", "Batman"};
13 | heroes.If(IsBestHero)
14 | .True(t => Assert.Equal("Conan", t))
15 | .False(f => falseHeroes.Add(f));
16 |
17 | Assert.Equal(2, falseHeroes.Count);
18 | }
19 |
20 | private bool IsBestHero(string hero)
21 | {
22 | return hero == "Conan";
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:36600",
8 | "sslPort": 44349
9 | }
10 | },
11 | "profiles": {
12 | "IIS Express": {
13 | "commandName": "IISExpress",
14 | "launchBrowser": true,
15 | "launchUrl": "weatherforecast",
16 | "environmentVariables": {
17 | "ASPNETCORE_ENVIRONMENT": "Development"
18 | }
19 | },
20 | "Nano.APIExample": {
21 | "commandName": "Project",
22 | "launchBrowser": true,
23 | "launchUrl": "weatherforecast",
24 | "applicationUrl": "https://localhost:5001;http://localhost:5000",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/Nano.DependencyInjector.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1
5 | Nano.DependencyInjector
6 | 1.0.0
7 | Baris Ceviz
8 | Nano.DependencyInjector
9 | Easy to apply dependency injection with aspect-oriented programming style
10 | Copyright @2020 Baris Ceviz
11 | https://github.com/peacecwz/nano-dependency-injector/blob/master/LICENSE
12 | https://github.com/peacecwz/nano-dependency-injector
13 | https://github.com/peacecwz/nano-dependency-injector.git
14 | git
15 | dependency-injector, dependency-injection, nano-dependency-injector
16 | true
17 | true
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Controllers/TestController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Mvc;
2 | using Nano.APIExample.Services;
3 |
4 | namespace Nano.APIExample.Controllers
5 | {
6 | [Route("v1/test")]
7 | public class TestController : Controller
8 | {
9 | private readonly ISingletonTestService _singletonTestService;
10 | private readonly IScopedTestService _scopedTestService;
11 | private readonly ITransientTestService _transientTestService;
12 |
13 | public TestController(ISingletonTestService singletonTestService, IScopedTestService scopedTestService,
14 | ITransientTestService transientTestService)
15 | {
16 | _singletonTestService = singletonTestService;
17 | _scopedTestService = scopedTestService;
18 | _transientTestService = transientTestService;
19 | }
20 |
21 | [HttpGet("singleton")]
22 | public string GetSingleton()
23 | {
24 | return _singletonTestService.Test();
25 | }
26 |
27 | [HttpGet("scoped")]
28 | public string GetScoped()
29 | {
30 | return _scopedTestService.Test();
31 | }
32 |
33 | [HttpGet("transient")]
34 | public string GetTransient()
35 | {
36 | return _transientTestService.Test();
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Controllers/WeatherForecastController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 | using Microsoft.Extensions.Logging;
7 |
8 | namespace Nano.APIExample.Controllers
9 | {
10 | [ApiController]
11 | [Route("[controller]")]
12 | public class WeatherForecastController : ControllerBase
13 | {
14 | private static readonly string[] Summaries = new[]
15 | {
16 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
17 | };
18 |
19 | private readonly ILogger _logger;
20 |
21 | public WeatherForecastController(ILogger logger)
22 | {
23 | _logger = logger;
24 | }
25 |
26 | [HttpGet]
27 | public IEnumerable Get()
28 | {
29 | var rng = new Random();
30 | return Enumerable.Range(1, 5).Select(index => new WeatherForecast
31 | {
32 | Date = DateTime.Now.AddDays(index),
33 | TemperatureC = rng.Next(-20, 55),
34 | Summary = Summaries[rng.Next(Summaries.Length)]
35 | })
36 | .ToArray();
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/tests/Nano.APIExample/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore.Builder;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.AspNetCore.HttpsPolicy;
9 | using Microsoft.AspNetCore.Mvc;
10 | using Microsoft.Extensions.Configuration;
11 | using Microsoft.Extensions.DependencyInjection;
12 | using Microsoft.Extensions.Hosting;
13 | using Microsoft.Extensions.Logging;
14 | using Nano.DependencyInjector;
15 |
16 | namespace Nano.APIExample
17 | {
18 | public class Startup
19 | {
20 | public Startup(IConfiguration configuration)
21 | {
22 | Configuration = configuration;
23 | }
24 |
25 | public IConfiguration Configuration { get; }
26 |
27 | // This method gets called by the runtime. Use this method to add services to the container.
28 | public void ConfigureServices(IServiceCollection services)
29 | {
30 | services.RegisterDependencies(Assembly.GetExecutingAssembly());
31 | services.AddControllers();
32 | }
33 |
34 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
35 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
36 | {
37 | if (env.IsDevelopment())
38 | {
39 | app.UseDeveloperExceptionPage();
40 | }
41 |
42 | app.UseHttpsRedirection();
43 |
44 | app.UseRouting();
45 |
46 | app.UseAuthorization();
47 |
48 | app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: publish to nuget
2 | on:
3 | push:
4 | branches:
5 | - master # Default release branch
6 | jobs:
7 | publish:
8 | name: build, pack & publish
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v2
12 |
13 | # Publish
14 | - name: Publish
15 | id: publish_nuget
16 | uses: rohith/publish-nuget@v2
17 | with:
18 | PROJECT_FILE_PATH: src/Nano.DependencyInjector/Nano.DependencyInjector.csproj
19 |
20 | # NuGet package id, used for version detection & defaults to project name
21 | PACKAGE_NAME: Nano.DependencyInjector
22 |
23 | # Filepath with version info, relative to root of repository & defaults to PROJECT_FILE_PATH
24 | VERSION_FILE_PATH: src/Nano.DependencyInjector/Nano.DependencyInjector.csproj
25 |
26 | # Regex pattern to extract version info in a capturing group
27 | VERSION_REGEX: ^\s*(.*)<\/PackageVersion>\s*$
28 |
29 | # Useful with external providers like Nerdbank.GitVersioning, ignores VERSION_FILE_PATH & VERSION_REGEX
30 | # VERSION_STATIC: 1.0.0
31 |
32 | # Flag to toggle git tagging, enabled by default
33 | TAG_COMMIT: true
34 |
35 | # Format of the git tag, [*] gets replaced with actual version
36 | # TAG_FORMAT: v*
37 |
38 | # API key to authenticate with NuGet server
39 | NUGET_KEY: ${{secrets.NUGET_API_KEY}}
40 |
41 | # NuGet server uri hosting the packages, defaults to https://api.nuget.org
42 | # NUGET_SOURCE: https://api.nuget.org
43 |
44 | # Flag to toggle pushing symbols along with nuget package to the server, disabled by default
45 | # INCLUDE_SYMBOLS: false
46 |
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/ListExtension.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | namespace Nano.DependencyInjector
6 | {
7 | public static class ListExtensions
8 | {
9 | public static ITrue If(this IEnumerable list, Predicate ifStatement)
10 | {
11 | var trueResult = list.Where(i => ifStatement(i));
12 | var falseResult = list.Where(i => !ifStatement(i));
13 |
14 | return new IfResult(trueResult, falseResult);
15 | }
16 | }
17 |
18 | public class IfResult : ITrue
19 | {
20 | private readonly IEnumerable trueResult;
21 | private readonly IEnumerable falseResult;
22 |
23 | public IfResult(IEnumerable trueResult, IEnumerable falseResult)
24 | {
25 | this.trueResult = trueResult;
26 | this.falseResult = falseResult;
27 | }
28 |
29 | public IFalse True(Action act)
30 | {
31 | foreach (var item in trueResult)
32 | {
33 | act(item);
34 | }
35 |
36 | return new ElseResult(falseResult);
37 | }
38 | }
39 |
40 | public class ElseResult : IFalse
41 | {
42 | private readonly IEnumerable falseResult;
43 |
44 | public ElseResult(IEnumerable falseResult)
45 | {
46 | this.falseResult = falseResult;
47 | }
48 |
49 | void IFalse.False(Action act)
50 | {
51 | foreach (var item in falseResult)
52 | {
53 | act(item);
54 | }
55 | }
56 | }
57 |
58 | public interface ITrue
59 | {
60 | IFalse True(Action act);
61 | }
62 |
63 | public interface IFalse
64 | {
65 | void False(Action act);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/DependencyInjectionConfigure.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reflection;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace Nano.DependencyInjector
7 | {
8 | internal static class DependencyInjectionConfigure
9 | {
10 | public static List GetDependencies(Assembly assembly)
11 | {
12 | var dependencies = new List();
13 | foreach (Type type in assembly.GetTypes())
14 | {
15 | var injectionType = GetInjectionType(type);
16 |
17 | if (!injectionType.HasValue)
18 | {
19 | continue;
20 | }
21 |
22 | dependencies.Add(new DependencyInjectionServiceType()
23 | {
24 | LifeTime = injectionType.Value,
25 | ImplementationType = type,
26 | InterfaceType =
27 | type.GetInterfaces()[
28 | 0] // TODO (peacecwz): Detect multiple interface and interface inject selection
29 | });
30 | }
31 |
32 | return dependencies;
33 | }
34 |
35 | private static ServiceLifetime? GetInjectionType(Type type)
36 | {
37 | if (type.GetCustomAttribute() != null)
38 | {
39 | return ServiceLifetime.Singleton;
40 | }
41 |
42 | if (type.GetCustomAttribute() != null)
43 | {
44 | return ServiceLifetime.Scoped;
45 | }
46 |
47 | if (type.GetCustomAttribute() != null)
48 | {
49 | return ServiceLifetime.Transient;
50 | }
51 |
52 | return null;
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/Nano.DependencyInjector.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D49F7FAA-60A5-4924-B35E-7197530987BB}"
4 | EndProject
5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D4271E6C-780C-4B0D-9CEE-C192A0088DCA}"
6 | EndProject
7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nano.DependencyInjector", "src\Nano.DependencyInjector\Nano.DependencyInjector.csproj", "{22D7E784-0B8E-447C-8B79-73C30759A858}"
8 | EndProject
9 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nano.APIExample", "tests\Nano.APIExample\Nano.APIExample.csproj", "{DB8AF37A-681B-48CF-8118-7D2E1518A439}"
10 | EndProject
11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nano.DependencyInjector.Tests", "tests\Nano.DependencyInjector.Tests\Nano.DependencyInjector.Tests.csproj", "{13C46E05-D404-4609-A82A-9CDDF653A9A1}"
12 | EndProject
13 | Global
14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
15 | Debug|Any CPU = Debug|Any CPU
16 | Release|Any CPU = Release|Any CPU
17 | EndGlobalSection
18 | GlobalSection(NestedProjects) = preSolution
19 | {22D7E784-0B8E-447C-8B79-73C30759A858} = {D49F7FAA-60A5-4924-B35E-7197530987BB}
20 | {DB8AF37A-681B-48CF-8118-7D2E1518A439} = {D4271E6C-780C-4B0D-9CEE-C192A0088DCA}
21 | {13C46E05-D404-4609-A82A-9CDDF653A9A1} = {D4271E6C-780C-4B0D-9CEE-C192A0088DCA}
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {22D7E784-0B8E-447C-8B79-73C30759A858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {22D7E784-0B8E-447C-8B79-73C30759A858}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {22D7E784-0B8E-447C-8B79-73C30759A858}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {22D7E784-0B8E-447C-8B79-73C30759A858}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {DB8AF37A-681B-48CF-8118-7D2E1518A439}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {DB8AF37A-681B-48CF-8118-7D2E1518A439}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {DB8AF37A-681B-48CF-8118-7D2E1518A439}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {DB8AF37A-681B-48CF-8118-7D2E1518A439}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {13C46E05-D404-4609-A82A-9CDDF653A9A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {13C46E05-D404-4609-A82A-9CDDF653A9A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {13C46E05-D404-4609-A82A-9CDDF653A9A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {13C46E05-D404-4609-A82A-9CDDF653A9A1}.Release|Any CPU.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # Nano Dependency Injector
2 |
3 | Easy to apply dependency injection into .NET Core Projects with Attributes like Spring Boot Applications
4 |
5 | ## Installation
6 |
7 | ```bash
8 | dotnet add package Nano.DependencyInjector
9 | ```
10 |
11 | ## Usage
12 |
13 | Define injection lifetime attribute to your injection class (Singleton, Scoped or Transient)
14 |
15 | ### Singleton Example
16 |
17 | ```cs
18 | public interface ISingletonTestService
19 | {
20 | string Test();
21 | }
22 |
23 | [Singleton] // Add attribute to service class
24 | public class SingletonTestService : ISingletonTestService
25 | {
26 | public SingletonTestService()
27 | {
28 | Console.WriteLine("Created singleton lifetime instance");
29 | }
30 |
31 | public string Test()
32 | {
33 | return "Singleton";
34 | }
35 | }
36 | ```
37 |
38 | ### Scoped Example
39 |
40 | ```cs
41 | public interface IScopedTestService
42 | {
43 | string Test();
44 | }
45 |
46 | [Scoped] // Add attribute to service class
47 | public class ScopedTestService : IScopedTestService
48 | {
49 | public ScopedTestService()
50 | {
51 | Console.WriteLine("Created scoped lifetime instance");
52 | }
53 |
54 | public string Test()
55 | {
56 | return "Scoped";
57 | }
58 | }
59 | ```
60 |
61 | ### Transient Example
62 |
63 | ```cs
64 | public interface ITransientTestService
65 | {
66 | string Test();
67 | }
68 |
69 | [Transient] // Add attribute to service class
70 | public class TransientTestService : ITransientTestService
71 | {
72 | public TransientTestService()
73 | {
74 | Console.WriteLine("Created transient lifetime instance");
75 | }
76 |
77 | public string Test()
78 | {
79 | return "Transient";
80 | }
81 | }
82 | ```
83 |
84 | ### Register Dependencies to IoC
85 |
86 | Add code to ```ConfigureServices``` on Startup.cs file and it will register all dependencies
87 |
88 | ```cs
89 | services.RegisterDependencies(Assembly.GetExecutingAssembly());
90 | ```
91 |
92 | ## TODO List
93 |
94 | * [x] Setup CI for publishing package on nuget
95 | * [ ] Add unit tests
96 | * [ ] Register named typed dependency
97 | * [ ] Inject name typed dependency
98 | * [ ] Add property injection without constructor
99 | * [ ] Register injectable multiple interfaces
100 | * [ ] Generic interfaces
101 |
102 | ## Contribution
103 |
104 | Feel the free for contribution. Open issues, PR and contact to me
105 |
106 | ## License
107 |
108 | This project is licensed under the MIT License
109 |
--------------------------------------------------------------------------------
/src/Nano.DependencyInjector/NanoDependencyInjectorExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Reflection;
4 | using Microsoft.Extensions.DependencyInjection;
5 |
6 | namespace Nano.DependencyInjector
7 | {
8 | public static class NanoDependencyInjectorExtensions
9 | {
10 | public static IServiceCollection RegisterDependencies(this IServiceCollection services, Assembly assembly)
11 | {
12 | DependencyInjectionConfigure.GetDependencies(assembly)
13 | .If(d => d.HasPropertyInjectAttribute())
14 | .True(services.AddPropertyInjectableTypes)
15 | .False(f => services.Add(
16 | new ServiceDescriptor(f.InterfaceType, f.ImplementationType, f.LifeTime)));
17 | return services;
18 | }
19 |
20 | private static void SetPropertyValue(IServiceProvider provider, object instance)
21 | {
22 | var injectableProperties = instance.GetType().GetProperties()
23 | .Where(p => p.GetCustomAttribute() != null)
24 | .ToList();
25 | foreach (var property in injectableProperties)
26 | {
27 | var value = provider.GetService(property.PropertyType);
28 | property.SetValue(instance, value);
29 | }
30 | }
31 |
32 | private static object CreateInstance(IServiceProvider provider, Type type)
33 | {
34 | object instance;
35 | ConstructorInfo publicConstructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public,
36 | null, new[] {typeof(string)}, null);
37 |
38 | if (publicConstructor == null)
39 | {
40 | instance = System.Runtime.Serialization.FormatterServices
41 | .GetUninitializedObject(type);
42 | SetPropertyValue(provider, instance);
43 | return instance;
44 | }
45 |
46 | var constructorPareParameters = publicConstructor.GetParameters();
47 |
48 | if (constructorPareParameters.Any())
49 | {
50 | var parameterInstances = constructorPareParameters
51 | .Select(parameter => provider.GetRequiredService(parameter.ParameterType)).ToList();
52 | instance = Activator.CreateInstance(type, parameterInstances);
53 | }
54 | else
55 | {
56 | instance = Activator.CreateInstance(type);
57 | }
58 |
59 | SetPropertyValue(provider, instance);
60 | return instance;
61 | }
62 |
63 | internal static void AddPropertyInjectableTypes(this IServiceCollection services,
64 | DependencyInjectionServiceType dependency)
65 | {
66 | switch (dependency.LifeTime)
67 | {
68 | case ServiceLifetime.Scoped:
69 | services.AddScoped(dependency.InterfaceType,
70 | provider => CreateInstance(provider, dependency.ImplementationType));
71 | break;
72 | case ServiceLifetime.Singleton:
73 | services.AddSingleton(dependency.InterfaceType,
74 | provider => CreateInstance(provider, dependency.ImplementationType));
75 | break;
76 | case ServiceLifetime.Transient:
77 | services.AddTransient(dependency.InterfaceType,
78 | provider => CreateInstance(provider, dependency.ImplementationType));
79 | break;
80 | default:
81 | throw new NotImplementedException();
82 | }
83 | }
84 |
85 | internal static bool HasPropertyInjectAttribute(this DependencyInjectionServiceType dependency)
86 | {
87 | return dependency.ImplementationType.GetProperties()
88 | .Any(p => p.GetCustomAttribute() != null);
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------