ServiceSharp 3.0.0
dotnet add package ServiceSharp --version 3.0.0
NuGet\Install-Package ServiceSharp -Version 3.0.0
<PackageReference Include="ServiceSharp" Version="3.0.0" />
<PackageVersion Include="ServiceSharp" Version="3.0.0" />
<PackageReference Include="ServiceSharp" />
paket add ServiceSharp --version 3.0.0
#r "nuget: ServiceSharp, 3.0.0"
#:package ServiceSharp@3.0.0
#addin nuget:?package=ServiceSharp&version=3.0.0
#tool nuget:?package=ServiceSharp&version=3.0.0
ServiceSharp
ServiceSharp is a tiny utility for registering services in Microsoft.Extensions.DependencyInjection with explicit attributes.
Version 3 is a breaking redesign. Service bindings are now declared directly on the implementation type. There is no marker-interface registration, no automatic "all interfaces" scan, and no hidden default lifetime.
The old v2 README is kept in READMEv2.MD.
Installation
Install from NuGet:
Install-Package ServiceSharp
Quick Start
Declare your services:
using ServiceSharp;
public interface IUserService
{
User GetCurrentUser();
}
[BindScoped(typeof(IUserService))]
public sealed class UserService : IUserService
{
public User GetCurrentUser()
{
// ...
}
}
Register them:
services.AddServiceSharp();
AddServiceSharp() registers services from the calling assembly. If the assembly contains ServiceSharp generated registration, that generated code is used. Otherwise, ServiceSharp falls back to reflection scanning.
You can also pass assemblies explicitly:
services.AddServiceSharp(
typeof(UserService).Assembly,
typeof(AnotherModuleMarker).Assembly);
Source Generation
ServiceSharp also ships a source generator in the same NuGet package.
Use generated registration when you want compile-time registration code instead of runtime reflection scanning:
using ServiceSharp.Generated.MyApp;
services.AddServiceSharpForMyApp();
The generated namespace and method name are based on the project assembly name. For example, an assembly named MyApp.Services gets:
using ServiceSharp.Generated.MyAppServices;
services.AddServiceSharpForMyAppServices();
The generated method registers services from the current compilation. Reflection registration is still available through AddServiceSharp(...), especially when you need to scan assemblies dynamically.
When registering multiple projects from an app, pass each assembly you want included:
services.AddServiceSharp(
typeof(MyLib.Marker).Assembly,
typeof(MyLib2.Marker).Assembly,
typeof(Program).Assembly);
ServiceSharp checks each assembly for generated registration first, then falls back to reflection for assemblies without generated registration.
Lifetimes
Use one of the lifetime attributes:
[BindSingleton]
public sealed class CacheService { }
[BindScoped(typeof(IUserService))]
public sealed class UserService : IUserService { }
[BindTransient(typeof(IEmailSender))]
public sealed class EmailSender : IEmailSender { }
Every registered implementation must specify a lifetime. If conflicting lifetimes are declared on the same implementation, ServiceSharp throws during registration.
Binding To Service Types
The preferred style is one lifetime attribute with all service types listed together:
[BindScoped(
typeof(IUserService),
typeof(IUserCache))]
public sealed class UserService :
IUserService,
IUserCache { }
Repeated attributes are valid when they use the same lifetime, but the single-attribute style is recommended:
[BindScoped(typeof(IUserService))]
[BindScoped(typeof(IUserCache))]
public sealed class UserService :
IUserService,
IUserCache { }
If no service type is supplied, the class is registered as itself:
[BindSingleton]
public sealed class AppClock { }
Convenience Bindings
BindToInterface binds to the single interface directly declared by the class:
[BindScoped, BindToInterface]
public sealed class UserService : IUserService { }
BindToBase binds to the immediate base class:
public abstract class RepositoryBase { }
[BindScoped, BindToBase]
public sealed class UserRepository : RepositoryBase { }
For clearer public APIs, prefer explicit service types when a class has more than one obvious binding.
Shared Instances
When one implementation is bound to multiple service types, singleton and scoped services resolve through one implementation registration.
[BindScoped(
typeof(IUserService),
typeof(IUserCache))]
public sealed class UserService :
IUserService,
IUserCache { }
Within one scope, resolving IUserService, IUserCache, or UserService returns the same instance.
Transient services still follow normal .NET DI transient behavior and create a new instance per resolution.
Migration From V2
V3 is intentionally not compatible with v2 declarations.
[Service(typeof(IFoo))]
becomes:
[BindScoped(typeof(IFoo))]
[SelfService]
becomes:
[BindScoped]
[Service]
has no automatic v3 equivalent. Choose the service types explicitly:
[BindScoped(
typeof(IFoo),
typeof(IBar))]
Choose BindSingleton, BindScoped, or BindTransient based on the lifetime you want.
| 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | 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.1
- Microsoft.Extensions.DependencyInjection (>= 10.0.9)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ServiceSharp:
| Package | Downloads |
|---|---|
|
ServiceSharp.AspNetCore
A tiny utility for Repository-Service pattern for ASP.NET Core |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0 | 97 | 7/7/2026 |
| 3.0.0-preview.2 | 45 | 7/7/2026 |
| 3.0.0-preview.1 | 54 | 7/7/2026 |
| 2.1.0 | 273 | 6/24/2025 |
| 2.0.0 | 360 | 7/24/2023 |
| 1.0.2 | 1,703 | 7/6/2018 |
| 1.0.1 | 1,597 | 7/6/2018 |
| 1.0.0 | 1,331 | 7/6/2018 |