# Dependency Injection

**Starting with Wisej.NET 3.1**, we added full support for services and dependency injection. Like everything else in Wisej.NET, it's a lean, performant, and flexible implementation.

If you need something more complex, we also support switching our [`IServiceProvider`](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider) with any third-party implementation, including Microsoft's DI, Autofac, or others.

{% hint style="success" %}
Our DI implementation is supported in both .NET 4.8 and .NET Core.
{% endhint %}

### Registering Services

You can register services at any point in the application. Services are always registered globally - if a service type is registered more than once, subsequent definitions replace the existing definition.

A good place to initialize services is in the static `Program` constructor, though you can register services anywhere in your code.

```csharp
static Program() {

  // Register an ILogger service implemented by MyLogger as a global shared singleton.
  Application.Services.AddService<ILogger, MyLogger>();
	
  // Register an IFileSystem service where the implementation is crated by the CreateFileSystemFactory method
  // and scope is set to be the session.
  Application.Services.AddService<IFileSystem>(CreateFileSystemFactory, ServiceLifetime.Session);
}

private static IFileSystem CreateFileSystemFactory(Type serviceType) {
  return new MyFileSystemImplementation();
}
```

The code above registers two services:

1. An `_ILogger_` implementation. Wisej.NET creates a `MyLogger` instance once (Global scope) on first use. This service is never disposed, even if it implements `_IDisposable_`, because it's registered with Shared lifetime as a singleton instance used by all sessions.
2. An `_IFileSystem_` service that delegates creation to the `_CreateFileSystemFactory_` method with Session scope. Wisej.NET invokes `_CreateFileSystemFactory_` on first request per session. The service instance is automatically disposed if it implements `_IDisposable_` when the session ends.

### Using a Service

Your code can request a service implementation in three ways:

* Using `_Application.Services.GetService<T>()_`
* Using the `_[Inject]_` attribute on a property
* Adding a service argument to the constructor of another service implementation

`_Application.GetService<T>()_` returns the service implementation for the requested T type if it exists, or null.

The `_[Inject]_` attribute works by default only on top-level UI containers: `_Page_`, `_Form_`, and `_Desktop_` classes. When you add the `_[Inject]_` attribute to a property (protected, private or public), Wisej.NET automatically resolves the service and assigns it during object construction.

```csharp
public class MyFileSystemImplementation : IFileSystem {

  [Inject]
  private ILogger Logger {get; set;}
  
  [Inject(Required = true]
  protected IVolumeManager Logger {get; set;}
}
```

{% hint style="info" %}
To use the `_[Inject]_` attribute on any object, call `_Application.Services.Inject(object)_`.
{% endhint %}

Services created by Wisej.NET can receive instances of other services by declaring them in the constructor.

```csharp
public class MyLoggerImplementationService : ILogger {
  public MyLoggerImplementationService(IFileSystem fileSystemService, ...) {
  
    // Wisej.NET resolves all the services in the constructor, if possible.
    // Unresolved services are simply set to null.
    
  }
}
```

### Service Injection

Wisej.NET supports Dependency Injection through constructors and property injection.

Property injection works automatically for all top-level containers (`Form`, `Page`, `Desktop`) and system-created services. Constructor injection works for service creation.

Example `MyFileSystemImplementation` with property injection:

```csharp
public class MyFileSystemImplementation : IFileSystem {

  [Inject]
  private ILogger Logger {get; set;}
	
  // Notes: The property can be protected, private or public.
  // If the service doesn't exist it will be null, unless the attribute is set to be required:
  // [Inject(Required=true)] in this case it throws an exception if the service is not available.
}
```

Constructor injection example (works only for system-created services):

```csharp
Application.Services.AddService<IFileSystem, MyFileSystemImplementation>(ServiceLifetime.Session);
	
...

public class MyFileSystemImplementation : IFileSystem {
	
  public MyFileSystemImplementation(ILogger logger, more services...) {
	
    // This constructor receives all the services it declared, if available, or null.
		
    // Wisej.NET detects circular dependencies and throws an exception instead of crashing
    // the server with a StackOverflow.

  }
}
```

To inject properties programmatically:

```csharp
Application.Services.Inject(object);
```

If the object declares any `_[Inject]_` properties, they receive service instances according to their lifetime.

### Generic Service Type

You can register generic types as services (starting from Wisej.NET 3.5.4) and request concrete service instances at runtime.

When requesting a service, Wisej.NET constructs or retrieves the correct instance of the generic type.

```csharp
// Register generic service
Application.Services.AddService(typeof(DBConnection<>));

// Request service
var dbTrucks = Application.Services.GetService<DBConnection<Truck>>);
var dbEmployees = Application.Services.GetService<DBConnection<Employee>>);
```

### Alternative IServiceProvider

To use a different service manager, register another [`IServiceProvider`](https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider) object.

<pre class="language-csharp"><code class="lang-csharp">// ASP.NET Core startup
public class Startup {
<strong>  public static void Main(string[] args) {
</strong>		
    var builder = WebApplication.CreateBuilder(new WebApplicationOptions
    {
      Args = args,
      WebRootPath = "./"
    });
	
    var app = builder.Build();

    // Register Microsoft's IServiceProvider with Wisej.NET.
    Application.Services.AddService&#x3C;IServiceProvider>(app.Services);
	
    app.UseWisej();
    app.UseFileServer();
    app.Run();
  }
}
</code></pre>

The line `Application.AddService<IServiceProvider>(app.Services);` registers Microsoft's `IServiceProvider` with Wisej.NET and replaces our `IServiceProvider`.

After this, `_Application.Services.AddService<T>()_` is not supported - all services must be registered using Microsoft's DI.

`_Application.Services.GetService<T>()_` and `_[Inject]_` use the alternative `IServiceProvider` to resolve services. The `IServiceProvider` instance is registered as a global singleton by default but can be registered per session using a different `ServiceLifetime` option.

### Services Lifetime

We support these service lifetimes:

* **Shared**: The service instance is a singleton used by all sessions and threads
* **Session**: The service instance is created per session and disposed (if `_IDisposable_`) when the session ends. Note that no other DI container supports session lifetime
* **Thread**: The service instance is created per thread (roughly corresponding to browser requests) and disposed (if `_IDisposable_`) when thread code ends
* **Transient**: The service instance is created on each request. It's never disposed - disposal responsibility (if `_IDisposable_`) lies with the caller

The default lifetime when registering a service is always `_Shared_`.
