Simple, lightweight & useful Dependency Injector for dotnet. |
-
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.
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 { }
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.
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>();
});
[InjectService] public IBookRepository BookRepository { get; private set; }
[InjectService] protected IBookRepository bookRepository;
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 meets your custom requirements such as defining lifetime, injecting into different interfaces, etc.
.Nurse provides fluent API to manage your injections from a single point.
services.AddServicesFrom("MyCompany.ProjectName.Services", ServiceLifetime.Scoped);
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"));
});
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");
});
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);
});
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"));
You can manage your injections for class by class.
[ServiceLifeTime(ServiceLifetime.Singleton)] // <-- Only this object will be Singleton.
public class MyRepository : IMyRepository
{
// ...
}
You can ignore some of your class from injector.
[DontRegister] // <-- This object will not be added into services
public class MyRepository : IMyRepository
{
// ...
}
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>();