/DotNurseInjector

Simple, lightweight & useful Dependency Injector for dotnet.

Primary LanguageC#MIT LicenseMIT

DotNurseInjector

.Nurse Injector

Simple, lightweight & useful Dependency Injector for dotnet.

.NET Core Nuget CodeFactor Gitmoji


Getting Started

  • Install Nuget package from here.

  • Go your Startup.cs, remove all your manual injections and use AddServicesFrom() method with namespace.

    • If you have following pattern:
services.AddTransient<IBookRepository, BookRepository>();
services.AddTransient<IAuthorRepository, AuthorRepository>();
services.AddTransient<IPublisherRepository, PublisherRepository>();
//...
  • Replace them with following:
services.AddServicesFrom("MyCompany.ProjectName.Repositories.Concrete"); // <-- Your implementations namespace.
  • That's it! DotNurse can find your namespace from any assembly. You don't need to send any Assembly parameter.

Property/Field Injection

This section is optional. You can still use default Microsoft Dependency Injection and skip this step.

You can use attribute injection instead of constructor injection. Using [InjectService] attribute for properties or fields is enough to inject them from IoC.

Setting Up

You must replace your Service Provider with .Nurse Injecor to use Attribute Injection.

  • Go your Program.cs and add UseDotNurseInjector() method to IHostBuilder.
 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseDotNurseInjector() // <-- Adding this one is enough!
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });

Usage

[InjectService] public IBookRepository BookRepository { get; set; }
[InjectService] public IBookRepository bookRepository;

dotnurse-injector-social-preview


Customizations

DotNurse meets your custom requirements such as a defining lifetime, injecting into different interfaces etc.


Managing from Startup

.Nurse provides fluent api to manage your injections from single point.

Service Lifetime

services.AddServicesFrom("MyCompany.ProjectName.Services", ServiceLifetime.Scoped);

Interface Selector

You can define a pattern to choose interface from multiple interfaces.

services.AddServicesFrom("ProjectNamespace.Services", ServiceLifetime.Scoped, opts =>
{
    opts.SelectInterface = interfaces => interfaces.FirstOrDefault(x => x.Name.EndsWith("Repository"));
});

Implementation Selector

You can define a pattern to choose which objects will be injected into IoC. For example you have a base type in same namespace and you don't want to add it into service collection. You can use this feature:

  • ProjectNamespace.Services
    • BookService
    • BaseService <- You want to ignore this
    • AuthorService
    • ...
services.AddServicesFrom("ProjectNamespace.Services", ServiceLifetime.Scoped, opts =>
{
    opts.SelectImplementtion = i => !i.Name.StartsWith("Base");
});

Implementation Base

Think about same scenario like previous, you can choose a base type to inject all classes which is inhetired from.

services.AddServicesFrom("ProjectNamespace.Services", ServiceLifetime.Scoped, opts =>
{
    opts.ImplementationBase = typeof(BaseRepository);
});

Adding Without Interface

You may want to use directly objects sometimes, if an abstraction has multiple implmentations. Then you can use AddWithoutInterfaceToo options as true. If you set this option as true, object will be added into services without interface too, like following:

services.AddServicesFrom("ProjectNamespace.Services", ServiceLifetime.Scoped, opts =>
{
    opts.AddWithoutInterfaceToo = true;
});

This makes something like following:

services.AddScoped<IBookService, BookService>();
services.AddScoped<BookService>(); // < -- Adds without interface too.
services.AddScoped<IAuthorService, AuthorService>();
services.AddScoped<AuthorService>(); // <-- Also for each pattern matched objects.
//...

Managing from Objects

You can manage your injections for class by class.

Service Lifetime Attribute

[ServiceLifeTime(ServiceLifetime.Singleton)] // <-- Only this object will be Singleton.
public class MyRepository : IMyRepository
{
    // ...
}

Ignore Injection Attribute

You can ignore some of your class from injector.

[IgnoreInjection] // <-- This object will not be added to services
public class MyRepository : IMyRepository
{
    // ...
}

Register As Attribute

You can manage your service types to add into. This attribute can be used multiple time at once.

/* 
 * Following object will be added into given types.
 */
[RegisterAs(typeof(IBookRepository))]
[RegisterAs(typeof(IBaseRepository<Book>), ServiceLifetime.Scoped)]
[RegisterAs(typeof(BookRepository), ServiceLifetime.Singleton)]
public class BookRepository : IBookRepository
{
    // ...
}

This injection will do following code:

services.AddTransient<IBookRepository, BookRepository>();
services.AddScoped<IBaseRepository<Book>>, BookRepository>();
services.AddSingleton<BookRepository>();