Skip to content

API Reference

Jim Burlison edited this page Dec 5, 2025 · 1 revision

API Reference

Complete API documentation for SSDI.

DependencyInjectionContainer

The main entry point for SSDI. Inherits from ActivationBuilder.

public class DependencyInjectionContainer : ActivationBuilder

Methods

Configure

Registers services with the container. Can be called multiple times.

public void Configure(Action<ExportRegistration> registration)

Example:

container.Configure(c =>
{
    c.Export<MyService>();
    c.Export<MyRepository>().As<IRepository>().Lifestyle.Singleton();
});

Locate<T>

Resolves a service by type.

public T Locate<T>()
public T Locate<T>(params DIParameter[] parameters)
public T Locate<T>(int position, object value)

Examples:

var service = container.Locate<IMyService>();

var player = container.Locate<Player>(
    DIParameter.Named("id", "player-1"));

var item = container.Locate<Item>(0, "sword");

Locate (non-generic)

Resolves a service by runtime type.

public object Locate(Type type)

Example:

Type serviceType = typeof(IMyService);
object service = container.Locate(serviceType);

LocateWithPositionalParams<T>

Resolves with positional parameters.

public T LocateWithPositionalParams<T>(params object[] parameters)

Example:

var server = container.LocateWithPositionalParams<Server>("localhost", 8080);

LocateWithNamedParameters<T>

Resolves with named parameters.

public T LocateWithNamedParameters<T>(params (string name, object value)[] parameters)

Example:

var server = container.LocateWithNamedParameters<Server>(
    ("host", "localhost"),
    ("port", 8080));

LocateWithTypedParams<T>

Resolves with type-matched parameters.

public T LocateWithTypedParams<T>(params object[] parameters)

Example:

var server = container.LocateWithTypedParams<Server>("localhost", 8080);

IsRegistered

Checks if a type is registered.

public bool IsRegistered<T>()
public bool IsRegistered(Type type)

Example:

if (container.IsRegistered<ILogger>())
{
    var logger = container.Locate<ILogger>();
}

Unregister

Removes a type registration. Disposes singleton instances if IDisposable.

public bool Unregister<T>(bool removeFromAliases = true)
public bool Unregister(Type type, bool removeFromAliases = true)

Parameters:

  • removeFromAliases: If true, also removes interface mappings. Default: true.

Returns: true if the type was registered and removed.

Example:

container.Unregister<OldService>();
container.Unregister<OldImpl>(removeFromAliases: false);

UnregisterAsync

Removes a type registration asynchronously. Properly awaits IAsyncDisposable.DisposeAsync() for singletons.

public Task<bool> UnregisterAsync<T>(bool removeFromAliases = true)
public Task<bool> UnregisterAsync(Type type, bool removeFromAliases = true)

Parameters:

  • removeFromAliases: If true, also removes interface mappings. Default: true.

Returns: Task containing true if the type was registered and removed.

Example:

await container.UnregisterAsync<AsyncDisposableService>();

UnregisterAll

Removes all implementations of an interface.

public int UnregisterAll<TAlias>()
public int UnregisterAll(Type aliasType)

Returns: Number of types unregistered.

Example:

int count = container.UnregisterAll<IPacketHandler>();

UnregisterAllAsync

Removes all implementations of an interface asynchronously.

public Task<int> UnregisterAllAsync<TAlias>()
public Task<int> UnregisterAllAsync(Type aliasType)

Returns: Task containing the number of types unregistered.

Example:

int count = await container.UnregisterAllAsync<IPacketHandler>();

CreateScope

Creates a new scope for scoped services.

public IScope CreateScope()

Example:

using var scope = container.CreateScope();
var service = scope.Locate<IScopedService>();

Properties

EagerCompilation

Controls when factories are compiled.

public bool EagerCompilation { get; set; }
  • false (default): Lazy compilation. Factories are compiled on first Locate<T>() call. Fast registration (~27μs), slower first-time resolution for each type.
  • true: Eager compilation. Factories are pre-compiled during Configure() with singletons embedded as constants. Slower registration (~10ms), fastest resolution (~19ns, near-parity with MS.DI/Grace).

Example:

// Lazy mode (default) - good for hot-swapping
var container = new DependencyInjectionContainer();

// Eager mode - for maximum resolution performance
var container = new DependencyInjectionContainer { EagerCompilation = true };

Events

Registered

Fires when a service is registered.

public event EventHandler<RegisteredEventArgs>? Registered

Example:

container.Registered += (sender, args) =>
{
    Console.WriteLine($"Registered: {args.RegisteredType.Name}");
};

RegisteredAsync

Fires asynchronously (fire-and-forget) when a service is registered.

public event Func<object?, RegisteredEventArgs, Task>? RegisteredAsync

Example:

container.RegisteredAsync += async (sender, args) =>
{
    await NotifyServiceDiscovery(args.RegisteredType);
};

Unregistered

Fires when a service is unregistered.

public event EventHandler<UnregisteredEventArgs>? Unregistered

Example:

container.Unregistered += (sender, args) =>
{
    Console.WriteLine($"Unregistered: {args.UnregisteredType.Name}");
};

UnregisteredAsync

Fires asynchronously (fire-and-forget) when a service is unregistered.

public event Func<object?, UnregisteredEventArgs, Task>? UnregisteredAsync

Example:

container.UnregisteredAsync += async (sender, args) =>
{
    await CleanupExternalResources(args.UnregisteredType);
};

ExportRegistration

Used within Configure() for registering services.

Methods

Export<T>

Registers a type.

public FluentExportRegistration Export<T>()
public FluentExportRegistration Export(Type type)

Example:

c.Export<MyService>();
c.Export(typeof(MyService));

ExportInstance<T>

Registers an existing instance as a singleton.

public FluentExportRegistration ExportInstance<T>(T instance)

Example:

c.ExportInstance(configuration).As<IConfiguration>();

FluentExportRegistration

Fluent API for configuring a registration.

Methods

As<TAlias>

Registers the type as an interface.

public FluentExportRegistration As<TAlias>()
public FluentExportRegistration As(Type type)

Example:

c.Export<SqlRepository>().As<IRepository>();
c.Export<UniversalService>().As<IReader>().As<IWriter>();

WithCtorParam

Provides constructor parameters.

public FluentExportRegistration WithCtorParam<TParam>(TParam value)
public FluentExportRegistration WithCtorParam(string name, object value)
public FluentExportRegistration WithCtorParam(int position, object value)
public FluentExportRegistration WithCtorParam(IDIParameter parameter)

Examples:

// By type
c.Export<Server>().WithCtorParam<int>(8080);

// By name
c.Export<Server>().WithCtorParam("port", 8080);

// By position
c.Export<Server>().WithCtorParam(0, "localhost");

WithCtorPositionalParams

Provides multiple positional parameters.

public FluentExportRegistration WithCtorPositionalParams(params object[] parameters)

Example:

c.Export<Server>().WithCtorPositionalParams("localhost", 8080, true);

Properties

Lifestyle

Access lifetime configuration.

public LifestyleScope Lifestyle { get; }

Example:

c.Export<MyService>().Lifestyle.Singleton();

LifestyleScope

Configures service lifetime.

Methods

Singleton

Service lives for the application lifetime.

public FluentExportRegistration Singleton()

Transient

New instance every resolution (default).

public FluentExportRegistration Transient()

Scoped

One instance per scope.

public FluentExportRegistration Scoped()

IScope

Represents a scope for scoped services.

public interface IScope : IDisposable, IAsyncDisposable

Properties

IsDisposed

Indicates if the scope has been disposed.

bool IsDisposed { get; }

Methods

All Locate methods from DependencyInjectionContainer are available:

T Locate<T>()
object Locate(Type type)
T Locate<T>(params DIParameter[] parameters)
T Locate<T>(int position, object value)
T LocateWithPositionalParams<T>(params object[] parameters)
T LocateWithNamedParameters<T>(params (string name, object value)[] parameters)
T LocateWithTypedParams<T>(params object[] parameters)

DIParameter

High-performance struct for parameter matching.

public readonly struct DIParameter

Static Methods

Named

Creates a parameter matched by name.

public static DIParameter Named(string name, object value)

Positional

Creates a parameter matched by position (0-based).

public static DIParameter Positional(int position, object value)

Typed

Creates a parameter matched by type.

public static DIParameter Typed(object value)

Methods

Matches

Checks if this parameter matches a constructor parameter.

public bool Matches(string parameterName, int parameterPosition, Type parameterType)

Legacy Parameter Classes

NamedParameter

Matches parameters by name.

public class NamedParameter : IDIParameter
{
    public NamedParameter(string name, object value)
}

PositionalParameter

Matches parameters by position.

public class PositionalParameter : IDIParameter
{
    public PositionalParameter(int position, object value)
}

TypedParameter

Matches parameters by type.

public class TypedParameter : IDIParameter
{
    public TypedParameter(object value)
}

IDIParameter

Interface for custom parameter matching.

public interface IDIParameter
{
    object Value { get; }
    bool GetParameterValue(string parameterName, int parameterPosition, Type parameterType);
}

RegisteredEventArgs

Event data for the Registered event.

public class RegisteredEventArgs : EventArgs

Properties

RegisteredType

The type that was registered.

public Type RegisteredType { get; }

Aliases

The alias types this registration is exposed as.

public IReadOnlyList<Type> Aliases { get; }

Lifestyle

The lifestyle of the registration.

public LifestyleType Lifestyle { get; }

HasInstance

Whether this is a singleton with a pre-existing instance.

public bool HasInstance { get; }

UnregisteredEventArgs

Event data for the Unregistered event.

public class UnregisteredEventArgs : EventArgs

Properties

UnregisteredType

The type that was unregistered.

public Type UnregisteredType { get; }

Instance

The singleton instance, if one existed. null for transient/scoped services.

public object? Instance { get; }

WasDisposed

Whether the instance was disposed during unregistration.

public bool WasDisposed { get; }

LifestyleType

Enum defining service lifetimes.

public enum LifestyleType
{
    Transient,  // New instance every resolution (default)
    Singleton,  // Single instance for app lifetime
    Scoped      // One instance per scope
}

Quick Reference

Registration Patterns

container.Configure(c =>
{
    // Basic
    c.Export<Service>();

    // Interface
    c.Export<Service>().As<IService>();

    // Instance
    c.ExportInstance(obj).As<IService>();

    // Lifetime
    c.Export<Service>().Lifestyle.Singleton();
    c.Export<Service>().Lifestyle.Scoped();

    // Parameters
    c.Export<Service>().WithCtorParam("name", value);
    c.Export<Service>().WithCtorParam(0, value);
    c.Export<Service>().WithCtorParam<int>(value);
});

Resolution Patterns

// Basic
var s = container.Locate<IService>();

// With parameters
var s = container.Locate<Service>(DIParameter.Named("id", 1));
var s = container.LocateWithPositionalParams<Service>(1, "name");
var s = container.LocateWithNamedParameters<Service>(("id", 1));
var s = container.LocateWithTypedParams<Service>(1, "name");

// Multiple implementations
var all = container.Locate<IEnumerable<IPlugin>>();

// Scoped
using var scope = container.CreateScope();
var s = scope.Locate<IScopedService>();

Unregistration Patterns

// Sync
container.Unregister<Service>();
container.UnregisterAll<IPlugin>();
bool exists = container.IsRegistered<IService>();

// Async (for IAsyncDisposable singletons)
await container.UnregisterAsync<AsyncService>();
await container.UnregisterAllAsync<IAsyncPlugin>();

Event Patterns

// Registration events
container.Registered += (sender, args) =>
{
    Console.WriteLine($"Registered: {args.RegisteredType.Name}");
};

container.RegisteredAsync += async (sender, args) =>
{
    await NotifyExternalSystem(args.RegisteredType);
};

// Unregistration events
container.Unregistered += (sender, args) =>
{
    if (args.WasDisposed)
        Console.WriteLine($"Disposed: {args.UnregisteredType.Name}");
};

container.UnregisteredAsync += async (sender, args) =>
{
    await CleanupResources(args.UnregisteredType);
};

Container Configuration

// Lazy mode (default) - fast registration, slower first resolution
var container = new DependencyInjectionContainer();

// Eager mode - slower registration, fastest resolution
var container = new DependencyInjectionContainer { EagerCompilation = true };

Clone this wiki locally