Dependency Injection
Services and Dependency Injection in 3.1.
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
with any third-party implementation, including Microsoft's DI, Autofac, or others.
Our DI implementation is supported in both .NET 4.8 and .NET Core.
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.
The code above registers two services:
An
_ILogger_
implementation. Wisej.NET creates aMyLogger
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.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 propertyAdding 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.
To use the _[Inject]_
attribute on any object, call _Application.Services.Inject(object)_
.
Services created by Wisej.NET can receive instances of other services by declaring them in the constructor.
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:
Constructor injection example (works only for system-created services):
To inject properties programmatically:
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.
Alternative IServiceProvider
To use a different service manager, register another IServiceProvider
object.
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 lifetimeThread: The service instance is created per thread (roughly corresponding to browser requests) and disposed (if
_IDisposable_
) when thread code endsTransient: 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_
.
Last updated