Devlooped.Extensions.DependencyInjection.Attributed
1.0.3
Prefix Reserved
See the version list below for details.
dotnet add package Devlooped.Extensions.DependencyInjection.Attributed --version 1.0.3
NuGet\Install-Package Devlooped.Extensions.DependencyInjection.Attributed -Version 1.0.3
<PackageReference Include="Devlooped.Extensions.DependencyInjection.Attributed" Version="1.0.3" />
paket add Devlooped.Extensions.DependencyInjection.Attributed --version 1.0.3
#r "nuget: Devlooped.Extensions.DependencyInjection.Attributed, 1.0.3"
// Install Devlooped.Extensions.DependencyInjection.Attributed as a Cake Addin #addin nuget:?package=Devlooped.Extensions.DependencyInjection.Attributed&version=1.0.3 // Install Devlooped.Extensions.DependencyInjection.Attributed as a Cake Tool #tool nuget:?package=Devlooped.Extensions.DependencyInjection.Attributed&version=1.0.3
Automatic compile-time service registrations for Microsoft.Extensions.DependencyInjection with no run-time dependencies.
Usage
After installing the nuget package,
by default a new [Service(ServiceLifetime)]
attribute will be available to annotate your types:
[Service(ServiceLifetime.Scoped)]
public class MyService : IMyService, IDisposable
{
public string Message => "Hello World";
public void Dispose() { }
}
public interface IMyService
{
string Message { get; }
}
The ServiceLifetime
argument is optional and defaults to ServiceLifetime.Singleton.
A source generator will emit (at compile-time) an AddServices
extension method for
IServiceCollection
which you can call from your startup code that sets up your services, like:
var builder = WebApplication.CreateBuilder(args);
// Add discovered services to the container.
builder.Services.AddServices();
// ...
var app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGet("/", (IMyService service) => service.Message);
// ...
app.Run();
NOTE: the service is available automatically for the scoped request.
And that's it. The source generator will discover annotated types in the current project and all its references too. Since the registration code is generated at compile-time, there is no run-time reflection (or dependencies) whatsoever.
How It Works
The generated code that implements the registration looks like the following:
services.AddScoped<MyService>();
services.AddScoped<IMyService>(s => s.GetRequiredService<MyService>());
services.AddScoped<IDisposable>(s => s.GetRequiredService<MyService>());
Note how the service is registered as scoped with its own type first, and the other two registrations just retrieve the same (according to its defined lifetime). This means the instance is reused and properly registered under all implemented interfaces automatically.
NOTE: you can inspect the generated code by setting
EmitCompilerGeneratedFiles=true
in your project file and browsing thegenerated
subfolder underobj
.
A linked source file named ServiceAttribute
is also added to the project by
the nuget package, but the source generator does not require it, since it matches
the annotation by attribute name.
Advanced Scenarios
Your Own ServiceAttribute
If you want to declare your own ServiceAttribute
and reuse from your projects,
you can do it too by setting the following property in your project file:
<PropertyGroup>
<IncludeServiceAttribute>false</IncludeServiceAttribute>
</PropertyGroup>
This will not add the attribute to the project's compilation. You can now create the attribute in your own shared library project like so:
[AttributeUsage(AttributeTargets.Class)]
public class ServiceAttribute : Attribute
{
public ServiceAttribute(ServiceLifetime lifetime = ServiceLifetime.Singleton) { }
}
NOTE: since the constructor argument is only used by the source generation to detemine the registration style, but never at run-time, you don't even need to keep it around in a field or property!
With this in place, you only need to add the package to the top-level project that is adding the services to the collection!
Customize Generated Class
You can customize the generated class namespace and name with the following MSBuild properties:
<PropertyGroup>
<AddServicesNamespace>MyNamespace</AddServicesNamespace>
<AddServicesClassName>MyExtensions</AddServicesClassName>
</PropertyGroup>
They default to Microsoft.Extensions.DependencyInjection
and AddServicesExtension
respectively.
Sponsors
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
2.1.0-beta | 62 | 11/12/2024 |
2.0.0 | 2,670 | 2/29/2024 |
1.3.2 | 7,133 | 12/13/2022 |
1.3.1 | 754 | 12/13/2022 |
1.3.0 | 792 | 12/6/2022 |
1.2.2 | 903 | 11/18/2022 |
1.2.1 | 857 | 11/16/2022 |
1.2.0 | 985 | 11/10/2022 |
1.1.3 | 781 | 10/31/2022 |
1.1.2 | 904 | 10/3/2022 |
1.1.1 | 869 | 10/3/2022 |
1.1.0 | 867 | 9/28/2022 |
1.0.3 | 895 | 9/27/2022 |