All Projects → pakrym → Jab

pakrym / Jab

Licence: mit
C# Source Generator based dependency injection container implementation.

Projects that are alternatives of or similar to Jab

ThunderboltIoc
One of the very first IoC frameworks for .Net that has no reflection. An IoC that casts its services before thunder casts its bolts.
Stars: ✭ 40 (-54.02%)
Mutual labels:  roslyn, dependency-injection
Fluent Symfony
Fluent configuration for Symfony
Stars: ✭ 80 (-8.05%)
Mutual labels:  dependency-injection
Enhanced Syntax Highlighting
[Marketplace] Lightweight "editor classifier extension" for Visual Studio based on the async Roslyn APIs to enhanced highlighting custom tags in C# code.
Stars: ✭ 69 (-20.69%)
Mutual labels:  roslyn
Dihedral
Compile-time dependency injection for Go
Stars: ✭ 76 (-12.64%)
Mutual labels:  dependency-injection
Bottlejs
A powerful dependency injection micro container for JavaScript applications
Stars: ✭ 1,171 (+1245.98%)
Mutual labels:  dependency-injection
Python Dependency Injector
Dependency injection framework for Python
Stars: ✭ 1,203 (+1282.76%)
Mutual labels:  dependency-injection
Di
psr/container implementation for humans
Stars: ✭ 69 (-20.69%)
Mutual labels:  dependency-injection
Fastify Decorators
Set of Typescript decorators to build Fastify server with controllers, services and hooks
Stars: ✭ 85 (-2.3%)
Mutual labels:  dependency-injection
Price Tracker
Price Tracking Application - An experimental Kotlin Android project with complex android app requirements.
Stars: ✭ 80 (-8.05%)
Mutual labels:  dependency-injection
Flutter Boilerplate Project
A boilerplate project created in flutter using MobX and Provider.
Stars: ✭ 1,194 (+1272.41%)
Mutual labels:  dependency-injection
Gistlyn
Run Roslyn Gists
Stars: ✭ 75 (-13.79%)
Mutual labels:  roslyn
Foal
Elegant and all-inclusive Node.Js web framework based on TypeScript. 🚀.
Stars: ✭ 1,176 (+1251.72%)
Mutual labels:  dependency-injection
Marinator
Delicious Dependency Injection
Stars: ✭ 79 (-9.2%)
Mutual labels:  dependency-injection
Forge
A Generic Low-Code Framework Built on a Config-Driven Tree Walker
Stars: ✭ 70 (-19.54%)
Mutual labels:  roslyn
Bankflix
Aplicação que simula um banco digital, contendo a área do cliente e administrativa, permitindo depósitos e transferências entre contas do mesmo banco. | Application that simulates a digital bank, containing the customer and administrative areas, allowing deposits and transfers between accounts of the same bank.
Stars: ✭ 82 (-5.75%)
Mutual labels:  dependency-injection
Android App Architecture Mvvm Databinding
A simple but complete project (in both Java & Kotlin) to demonstrate the Android application architecture with MVVM pattern, a client app for The Movie DB Web API. Dagger2 is used for dependency injection and RxJava is used for RFP (Reactive Functional Programming).
Stars: ✭ 69 (-20.69%)
Mutual labels:  dependency-injection
Git Rocket Filter
Rewrite git branches in a powerful way
Stars: ✭ 73 (-16.09%)
Mutual labels:  roslyn
Dikit
Dependency Injection Framework for Swift, inspired by KOIN.
Stars: ✭ 77 (-11.49%)
Mutual labels:  dependency-injection
Alfa
Effortless React State Management.
Stars: ✭ 86 (-1.15%)
Mutual labels:  dependency-injection
Getting Started Koin Android
Getting started project with a Android & Koin
Stars: ✭ 83 (-4.6%)
Mutual labels:  dependency-injection

Jab Compile Time Dependency Injection

Nuget (with prereleases)

Jab provides a C# Source Generator based dependency injection container implementation.

  • Fast startup (200x faster than Microsoft.Extensions.DependencyInjection). Details.
  • Fast resolution (7x faster than Microsoft.Extensions.DependencyInjection). Details.
  • No runtime dependencies.
  • AOT and linker friendly, all code is generated during project compilation.
  • Clean stack traces:

    stacktrace

  • Readable generated code:

    generated code

  • Registration validation. Container configuration issues become compiler errors:

    generated code

Example

Add Jab package reference:

<ItemGroup>
    <PackageReference Include="Jab" Version="0.0.2-beta.105" PrivateAssets="all" />
</ItemGroup>

Define a service and implementation:

internal interface IService
{
    void M();
}

internal class ServiceImplementation : IService
{
    public void M()
    {
    }
}

Define a composition root and register services:

[ServiceProvider]
[Transient(typeof(IService), typeof(ServiceImplementation))]
internal partial class MyServiceProvider { }

Use the service provider:

MyServiceProvider c = new MyServiceProvider();
IService service = c.GetService<IService>();

Features

  • No runtime dependency, safe to use in libraries
  • Transient, Singleton, Scoped service registration
  • Factory registration
  • Instance registration
  • IEnumerable resolution
  • IDisposable and IAsyncDisposable support
  • IServiceProvider support

The plan is to support the minimum feature set Microsoft.Extensions.DependencyInjection.Abstraction requires but NOT the IServiceCollection-based registration syntax as it is runtime based.

Singleton services

Singleton services are created once per container lifetime in a thread-safe manner and cached. To register a singleton service use the SingletonAttribute:

[ServiceProvider]
[Singleton(typeof(IService), typeof(ServiceImplementation))]
internal partial class MyServiceProvider { }

Singleton Instances

If you want to use an existing object as a service define a property in the container declaration and use the Instance property of the SingletonAttribute to register the service:

[ServiceProvider]
[Singleton(typeof(IService), Instance = nameof(MyServiceInstance))]
internal partial class MyServiceProvider {
    public IService MyServiceInstance { get;set; }
}

Then initialize the property during the container creation:

MyServiceProvider c = new MyServiceProvider();
c.MyServiceInstance = new ServiceImplementation();

IService service = c.GetService<IService>();

Factories

Sometimes it's useful to provide a custom way to create a service instance without using the automatic construction selection. To do this define a method in the container declaration and use the Factory property of the SingletonAttribute or TransientAttribute to register the service:

[ServiceProvider]
[Transient(typeof(IService), Factory = nameof(MyServiceFactory))]
internal partial class MyServiceProvider {
    public IService MyServiceFactory() => new ServiceImplementation();
}

MyServiceProvider c = new MyServiceProvider();
IService service = c.GetService<IService>();

When using with TransientAttribute the factory method would be invoked for every service resolution. When used with SingletonAttribute it would only be invoked the first time the service is requested.

Scoped Services

Scoped services are created once per service provider scope. To create a scope use the CreateScope() method of the service provider. Service are resolved from the scope using the GetService<IService>() call.

[ServiceProvider]
[Scoped(typeof(IService), typeof(ServiceImplementation))]
internal partial class MyServiceProvider { }

MyServiceProvider c = new MyServiceProvider();
using MyServiceProvider.Scope scope = c.CreateScope();
IService service = scope.GetService<IService>();

When the scope is disposed all IDisposable and IAsyncDisposable services that were resolved from it are disposed as well.

Modules

Often, a set of service registrations would represent a distinct set of functionality that can be included into arbitrary service provider. Modules are used to implement registration sharing. To define a module create an interface and mark it with ServiceProviderModuleAttribute. Service registrations can be listed in module the same way they are in the service provider.

[ServiceProviderModule]
[Singleton(typeof(IService), typeof(ServiceImplementation))]
public interface IMyModule
{
}

To use the module apply the Import attribute to the service provider type:

[ServiceProvider]
[Import(typeof(IMyModule))]
internal partial class MyServiceProvider
{
}

MyServiceProvider c = new MyServiceProvider();
IService service = c.GetService<IEnumerable<IService>>();

Modules can import other modules as well.

NOTE: module service and implementation types have to be accessible from the project where service provider is generated.

Root services

By default, IEnumerable<...> service accessors are only generated when requested by other service constructors. If you would like to have a root IEnumerable<..> accessor generated use the RootService parameter of the ServiceProvider attribute. The generator also scans all the GetService<...> usages and tries to all collected type arguments as the root service.

[ServiceProvider(RootServices = new [] {typeof(IEnumerable<IService>)})]
[Singleton(typeof(IService), typeof(ServiceImplementation))]
[Singleton(typeof(IService), typeof(ServiceImplementation))]
[Singleton(typeof(IService), typeof(ServiceImplementation))]
internal partial class MyServiceProvider
{
}

MyServiceProvider c = new MyServiceProvider();
IService service = c.GetService<IEnumerable<IService>>();

Samples

Console application

Sample Jab usage in console application can be found in src/samples/ConsoleSample

Performance

The performance benchmark project is available in src/Jab.Performance/.

Startup time

The startup time benchmark measures time between application startup and the first service being resolved.

| Method |        Mean |     Error |    StdDev |  Ratio | RatioSD |  Gen 0 |  Gen 1 | Gen 2 | Allocated |
|------- |------------:|----------:|----------:|-------:|--------:|-------:|-------:|------:|----------:|
|   MEDI | 2,437.88 ns | 14.565 ns | 12.163 ns | 220.91 |    2.72 | 0.6332 | 0.0114 |     - |    6632 B |
|    Jab |    11.03 ns |  0.158 ns |  0.123 ns |   1.00 |    0.00 | 0.0046 |      - |     - |      48 B |

GetService

The GetService benchmark measures the provider.GetService<IService>() call.

| Method |      Mean |     Error |    StdDev | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------- |----------:|----------:|----------:|------:|--------:|-------:|------:|------:|----------:|
|   MEDI | 39.340 ns | 0.2419 ns | 0.2263 ns |  7.01 |    0.09 | 0.0023 |     - |     - |      24 B |
|    Jab |  5.619 ns | 0.0770 ns | 0.0643 ns |  1.00 |    0.00 | 0.0023 |     - |     - |      24 B |

Debugging locally

Run dotnet build /t:CreateLaunchSettings in the Jab.Tests directory would update the Jab\Properties\launchSettings.json file to include csc invocation that allows F5 debugging of the generator targeting the Jab.Tests project.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].