Code Monkey home page Code Monkey logo

firefly.dependencyinjection's Introduction

Attribute-driven Service Registration

NuGet NuGet license


// Declaration
[RegisterScoped(Type = typeof(IMyService))]
public class MyServiceImplementation : IMyService
{}

// Consumer
[RegisterScoped]
public class MyServiceConsumer(){
    public MyServiceConsumer(IMyService myService)
    {
        ...
    }
}

Features

  • Simple and fast service registration with single attribute
  • All service lifetimes supported, of course
  • Binding interface to one or more implementations with option to expose concrete types as well
  • Select which assemblies will be scanned for auto-registration
  • Possibility to select a single i-face implementation of many based on your custom logic

Installation

Linux/OSX

dotnet add package Firefly.DependencyInjection

Windows

Install-Package Firefly.DependencyInjection

.csproj

<PackageReference Include="Firefly.DependencyInjection" />

Basic Setup

During application startup, find a IServiceCollection instance and call AddFireflyServiceRegistration().

The location depends on your Hosting Model:

WebApplicationBuilder

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFireflyServiceRegistration();

Older Startup.cs

public virtual void ConfigureServices(IServiceCollection services)
{
    services.AddFireflyServiceRegistration();
}

Manually created ServiceCollction

var sc = new ServiceCollection()
sc.AddFireflyServiceRegistration();

Usage

Service Lifetimes

// All three lifetimes are expressed by attributes

[RegisterTransient]
public class MyTransientService {}

[RegisterSingleton]
public class MyScopedService {}

[RegisterScoped]
public class MyScopedService {}

Using interfaces

// Declaration
[RegisterScoped(Type = typeof(IMyService))]
public class MyServiceImplementation : IMyService
{}

// Consumer
[RegisterScoped]
public class MyServiceConsumer(){
    public MyServiceConsumer(IMyService myService)
    {
        ...
    }
}

Multiple implementations of an interface

[RegisterScoped(Type = typeof(IMyService))] 
public class MyServiceA : IMyService {} // Variant A

[RegisterScoped(Type = typeof(IMyService))] 
public class MyServiceB : IMyService {} // Variant B

[RegisterScoped]
public class Consumer 
{
    // Services will be injected the same way as you're used to.
    public Consumer(ICollection<IMyService> myInstances){}
}

Registering concrete types along with its interface

By default, if a service is registered with an interface, the concrete implementation is not registered into the container. With RegisterAllImplementations(true), not only the interface but even the derived type(s) will be registered.

// Setup
services.AddFireflyServiceRegistration(builder => {
    builder.RegisterAllImplementations()    
});

// Declaration
[RegisterScoped(Type = typeof(IMyService))]
public class MyServiceImplementation : IMyService {}

// Consumer
[RegisterScoped]
public class MyServiceConsumer(){
    public MyServiceConsumer(IMyService ifaceImpl, MyServiceImplementation concreteImpl)
    {
        // Both dependencies are resolved
        Asert.True(ifaceImpl.GetType() == concreteImpl.GetType());
    }
}

Note

If the service lifetime is Transient, both object will have different instances.

Picking single implementation of an interface from many

There can be a situation where you need to choose an implementation at the runtime. This is an example of choosing an filesystem provider based on a string during the application startup.

Let's have two different impl. of a IFileProvider interface.

// Implementation A
[RegisterScoped(Type = typeof(IFileProvider))]
public class BlobFileProvider : IFileProvider {} 

// Implementation B
[RegisterScoped(Type = typeof(IFileProvider))]
public class LocalFileProvider : IFileProvider {}

Application startup:

var useLocalFiles = true;

services.AddFireflyServiceRegistration(builder => {
    if (useLocalFiles)
        builder.PickSingleImplementation<IFileProvider>(typeof(LocalFileProvider));
    else
        builder.PickSingleImplementation<IFileProvider>(typeof(BlobFileProvider));
});

The consuming service:

public class FilesystemConsumer {
    public FilesystemConsumer(IFileProvider provider){
        // provider will LocalFileProvider
    }
}

You may also use another two overrides that allow you to pass the Types via Type Parameters or via Type function argument.

// From DiRegistrationBuilder: 
public DiRegistrationBuilder PickSingleImplementation(Type interfaceType, Type concreteType);
public DiRegistrationBuilder PickSingleImplementation<TInterface>(Type concreteType);
public DiRegistrationBuilder PickSingleImplementation<TInterface, TConcrete>()

Registering services from other Assemblies

It's fully possible to include another assembly. All these assemblies will be scanned for [Register*] attributes.

Important

Referencing an assembly is needed if you want to register services from another project in your solution.

services.AddFireflyServiceRegistration(builder => {
    builder.UseAssembly("Example.Assembly.Name"); // Locate assembly by string
    builder.UseAssembly(Assembly.GetEntryAssembly()); // Specify assembly by the Assembly type and pass anything you need.
});

firefly.dependencyinjection's People

Contributors

rudolfdobias avatar

Stargazers

 avatar Kateřina Břicháčková avatar

Watchers

James Cloos avatar  avatar

Forkers

andrewinside

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.