-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
This guide walks you from NuGet installation to your first evaluated flag in a .NET 10 application.
| Requirement | Details |
|---|---|
| .NET SDK | 10.0 or later |
| Supported platforms |
net10.0 (Linux, Windows), net10.0-android, net10.0-ios, net10.0-maccatalyst, net10.0-windows10.0.19041.0
|
| Dependency injection |
Microsoft.Extensions.DependencyInjection (any version compatible with .NET 10) |
Install the packages from NuGet. You will need at minimum the runtime SDK. The Build package is required only if you want MSBuild manifest embedding (recommended for production).
<!-- runtime SDK - evaluates flags and uploads exposures -->
<PackageReference Include="SharpNinja.FeatureFlags" Version="1.0.0" />
<!-- public contracts, types, and interfaces -->
<PackageReference Include="SharpNinja.FeatureFlags.Abstractions" Version="1.0.0" />
<!-- MSBuild integration: manifest embedding, identity stamping, source generation -->
<PackageReference Include="SharpNinja.FeatureFlags.Build" Version="1.0.0" />SharpNinja.FeatureFlags already depends on SharpNinja.FeatureFlags.Abstractions, so you only need to list Abstractions explicitly when a project references the contracts without the full runtime (for example, a library project that only uses ISharpNinjaFeatureClient).
When SharpNinja.FeatureFlags.Build is referenced, its build-transitive targets run automatically. Tell them about your product by setting two properties:
<PropertyGroup>
<!-- required: identifies which product's manifest to load -->
<ProductId>truckmate</ProductId>
<!-- required: identifies the exact release being shipped -->
<ReleaseId>truckmate-1.2.0-stable-0</ReleaseId>
<!-- optional: path to the manifest JSON file (default: $(MSBuildProjectDirectory)\flags\flags.json) -->
<SharpNinjaFeatureFlagsManifest>$(MSBuildProjectDirectory)\flags\flags.json</SharpNinjaFeatureFlagsManifest>
<!-- optional: path to the Ed25519 public key file (default: $(MSBuildProjectDirectory)\flags\public-key.ed25519) -->
<SharpNinjaFeatureFlagsPublicKey>$(MSBuildProjectDirectory)\flags\public-key.ed25519</SharpNinjaFeatureFlagsPublicKey>
</PropertyGroup>See MSBuild Integration for the full property reference.
Call AddSharpNinjaFeatureFlags on your IServiceCollection. The method requires an options record and the raw manifest JSON.
using Microsoft.Extensions.DependencyInjection;
using SharpNinja.FeatureFlags;
using SharpNinja.FeatureFlags.Abstractions.Options;
// Build your options. All five constructor parameters are required.
var options = new SharpNinjaFeatureFlagOptions(
productId: "truckmate",
releaseId: "truckmate-1.2.0-stable-0",
environment: "production",
manifestRefreshInterval: TimeSpan.FromMinutes(5),
exposureUploadInterval: TimeSpan.FromSeconds(30));
// Load the manifest JSON however is appropriate for your app.
// For a bundled resource, use Assembly.GetManifestResourceStream.
string manifestJson = File.ReadAllText("flags/flags.json");
ServiceCollection services = new();
services.AddSharpNinjaFeatureFlags(options, manifestJson);
ServiceProvider provider = services.BuildServiceProvider();When SharpNinjaFeatureFlagsGenerateRegistrationSource is set to true in your project file, the Build target generates a zero-argument overload that reads the embedded resource and uses the MSBuild property values for ProductId, ReleaseId, and environment automatically:
// Generated by the Build target - no arguments needed.
services.AddSharpNinjaFeatureFlags();See MSBuild Integration for how to enable source generation.
// Overload 1: raw manifest JSON (uses a development-only structural signature internally)
public static IServiceCollection AddSharpNinjaFeatureFlags(
this IServiceCollection services,
SharpNinjaFeatureFlagOptions options,
string manifestJson);
// Overload 2: pre-built signed envelope (production path - carries signature, key ID, and algorithm)
public static IServiceCollection AddSharpNinjaFeatureFlags(
this IServiceCollection services,
SharpNinjaFeatureFlagOptions options,
SignedManifestEnvelope manifestEnvelope);Resolve ISharpNinjaFeatureClient from the container and call Evaluate<T>. The method never blocks on network state - it always returns synchronously from the in-memory manifest.
using SharpNinja.FeatureFlags.Abstractions;
ISharpNinjaFeatureClient client = provider.GetRequiredService<ISharpNinjaFeatureClient>();
// Synchronous evaluation
EvaluationResult<bool> result = client.Evaluate(
key: "dashboard.enabled",
defaultValue: false);
if (result.Value)
{
Console.WriteLine("Dashboard is enabled.");
}
Console.WriteLine($"Resolved by: {result.Reason}"); // e.g. RuleMatch, Default, DisabledPass caller-specific attributes via EvaluationContext to target rules by user, tenant, or any custom dimension:
EvaluationContext context = EvaluationContext.Builder()
.Set("project.id", "truckmate")
.Set("user.role", "admin")
.Build();
EvaluationResult<string> title = client.Evaluate(
key: "reports.title",
defaultValue: "Reports",
context: context);
Console.WriteLine(title.Value); // e.g. "TruckMate Reports"EvaluateAsync provides an async-compatible surface. The current implementation resolves synchronously but the signature supports future network-aware evaluation without breaking callers.
EvaluationResult<bool> result = await client.EvaluateAsync(
key: "new-ui.enabled",
defaultValue: false,
context: context,
cancellationToken: cancellationToken);| Property | Type | Description |
|---|---|---|
Value |
T |
The resolved flag value |
Reason |
EvaluationReason |
Why the value was chosen |
Variant |
string? |
Matched variant identifier, if any |
RuleIndex |
int? |
Zero-based index of the matched rule, if any |
ErrorMessage |
string? |
Error detail when Reason is Error
|
EvaluationReason values: Unknown, Default, RuleMatch, TargetingMatch, Disabled, Error.
-
Bundled manifest loaded first. The manifest JSON you provide (or embed via the Build target) is parsed and validated against
ProductId,ReleaseId, andEnvironment. A mismatch throws at registration time so misconfigured apps fail fast. -
Disk cache checked.
SharpNinjaDiskManifestCacheStorelooks for a previously fetched manifest in%LOCALAPPDATA%\SharpNinja\FeatureFlags\{productId}\{releaseId}\{environment}\manifest-cache.json. When found and its signature is valid, the cached manifest replaces the bundled one. Evaluation is immediately available with the fresher data. -
Background refresh scheduled. If
DistributionBaseUriis configured,SharpNinjaRemoteFetchCoordinatorfetches the manifest from the distribution service on theManifestRefreshIntervalcadence. Successful responses are signature-verified, activated in memory, and written to the disk cache. -
Exposure events buffered and uploaded. Every
Evaluatecall records aSharpNinjaExposureEventto the file-backed outbox. A background coordinator drains the outbox on theExposureUploadIntervalcadence and POSTs batches to the configuredExposureUploadEndpointor derives the endpoint fromDistributionBaseUri.
All evaluation calls are lock-free reads against the current in-memory manifest. Network failures never affect evaluation latency.