Skip to content

Latest commit

 

History

History
243 lines (187 loc) · 6.97 KB

README.md

File metadata and controls

243 lines (187 loc) · 6.97 KB

DotNurseInjector

.Nurse Injector

Simple, lightweight & useful Dependency Injector for dotnet.

.NET Core Nuget CodeFactor Gitmoji


Getting Started

  • Install Nuget package from here.

  • Go to 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 will scan your entire assembly and referenced assemblies to find types with the given namespace then register them to ServiceCollection.

Managing in Objects

You can even define lifetimes and expose types from objects via using [RegisterAs] attribute.

  • Firstly, you should add following method for registering by attributes.
    services.AddServicesByAttributes();
  • Then you're ready to decorate your objects with [RegisterAs] attribute.
    [RegisterAs(typeof(IBookRepository))]
    public class BookRepository : IBookRepository, IAnotherInterface, IYetAnothetInterface
    {
    }

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; private set; }
[InjectService] protected IBookRepository bookRepository;

Refactor your old codes

You can remove long constructor and place attribute to your fields or properties.

  • Old code before DotNurseInjector
public class BookService 
{
  public IBookRepository BookRepository { get; private set; }
  private readonly BookManager _bookManager;
  // ...
  
  public BookService(
    IBookRepository bookRepository,
    BookManager bookManager,
    // ... 
    )
  {
     BookRepository = bookRepository;
     _bookManager = bookManager;
     // ...
  }
}
  • New code after DotNutseInjector
public class BookService 
{
  [InjectService] private IBookRepository BookRepository { get; set; }
  [InjectService] private readonly BookManager _bookManager;
  // ...
}

dotnurse-injector-social-preview


Customizations

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


Managing from Startup

.Nurse provides fluent API to manage your injections from a 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);
});

Custom Registration Rule

You can use lambda expression to define your custom rules for registration.

In example, you can use it for registering types in a namespace recursively.

// Following code will register all types under Services namespace and sub-namespaces too.
services.AddServicesFrom(
    x => x.Namespace != null && (x.Namespace.StartsWith("MyProject.Services"));

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
{
    // ...
}

Ignoring Registration by Attribute

You can ignore some of your class from injector.

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

Register As Attribute

You can manage your service types to add into. This attribute can be used multiple times 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>();