Table of Contents

Class OptunaServiceCollectionExtensions

Namespace
OptunaSharp.Extensions
Assembly
OptunaSharp.dll

Microsoft.Extensions.DependencyInjection wire-up for OptunaSharp's core building blocks: register the app-wide BaseSampler, BasePruner and BaseStorage once, then resolve an IOptunaStudyFactory that composes them into studies. This is a .NET-ergonomics layer over the functional CreateStudy(BaseStorage?, BaseSampler?, BasePruner?, string?, StudyDirection?, bool, IEnumerable<StudyDirection>?) API — it changes nothing about how a study behaves, only where it is configured.

The registrations compose with the satellite packages: e.g. services.AddSqliteStorage("sqlite:///study.db").AddBoTorchSampler().AddOptunaStudyFactory() wires storage + sampler + factory across three assemblies with no glue code.

Lifetimes. Samplers and pruners hold per-study state (RNG streams, generation trackers, search-space caches), so their factory registrations default to Transient: every study the factory builds gets its own instance, as every Python create_study() call builds its own default sampler. Storages are shared infrastructure and default to Singleton. An instance registration is always a singleton, shared by every study.

public static class OptunaServiceCollectionExtensions
Inheritance
OptunaServiceCollectionExtensions
Inherited Members

Examples

services.AddOptunaSampler(new TPESampler(seed: 0));
services.AddOptunaStorage("sqlite:///study.db");
services.AddOptunaStudyFactory(o => o.DefaultDirection = StudyDirection.Maximize);
// elsewhere:  var study = provider.GetRequiredService<IOptunaStudyFactory>().CreateStudy("run-42");

Methods

AddOptunaPruner(IServiceCollection, BasePruner)

Register a pre-built pruner as the application's BasePruner singleton. Every study shares it: harmless for the stateless pruners (median, percentile, threshold), wrong for one that caches per-study setup such as HyperbandPruner. Use the factory overload for those.

public static IServiceCollection AddOptunaPruner(this IServiceCollection services, BasePruner pruner)

Parameters

services IServiceCollection

The service collection to add to.

pruner BasePruner

The pruner instance shared by every study built from this container.

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or pruner is null.

AddOptunaPruner(IServiceCollection, Func<IServiceProvider, BasePruner>, ServiceLifetime)

Register a pruner produced by a factory, so its construction can depend on other services and each study can get its own instance.

public static IServiceCollection AddOptunaPruner(this IServiceCollection services, Func<IServiceProvider, BasePruner> factory, ServiceLifetime lifetime = ServiceLifetime.Transient)

Parameters

services IServiceCollection

The service collection to add to.

factory Func<IServiceProvider, BasePruner>

Builds the pruner from the resolved IServiceProvider.

lifetime ServiceLifetime

The registration lifetime; defaults to Transient, so the study factory hands every study a fresh pruner (a HyperbandPruner sizes its brackets from the first study it sees).

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or factory is null.

AddOptunaSampler(IServiceCollection, BaseSampler)

Register a pre-built sampler as the application's BaseSampler singleton. Footgun: every study the factory builds then shares this one instance, and most samplers keep per-study state (the GA samplers' generation trackers, an RNG stream, TPE's search-space cache) and are not thread-safe. Prefer the factory overload, whose default lifetime is transient, unless exactly one study uses the container at a time.

public static IServiceCollection AddOptunaSampler(this IServiceCollection services, BaseSampler sampler)

Parameters

services IServiceCollection

The service collection to add to.

sampler BaseSampler

The sampler instance shared by every study built from this container.

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or sampler is null.

AddOptunaSampler(IServiceCollection, Func<IServiceProvider, BaseSampler>, ServiceLifetime)

Register a sampler produced by a factory, so its construction can depend on other services and each study can get its own instance.

public static IServiceCollection AddOptunaSampler(this IServiceCollection services, Func<IServiceProvider, BaseSampler> factory, ServiceLifetime lifetime = ServiceLifetime.Transient)

Parameters

services IServiceCollection

The service collection to add to.

factory Func<IServiceProvider, BaseSampler>

Builds the sampler from the resolved IServiceProvider.

lifetime ServiceLifetime

The registration lifetime; defaults to Transient, so the study factory hands every study a fresh sampler. Singleton shares one sampler, and its per-study state, across all studies.

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or factory is null.

AddOptunaStorage(IServiceCollection, BaseStorage)

Register a pre-built storage as the application's BaseStorage singleton.

public static IServiceCollection AddOptunaStorage(this IServiceCollection services, BaseStorage storage)

Parameters

services IServiceCollection

The service collection to add to.

storage BaseStorage

The storage instance shared by every study built from this container.

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or storage is null.

AddOptunaStorage(IServiceCollection, Func<IServiceProvider, BaseStorage>, ServiceLifetime)

Register a storage produced by a factory, so its construction can depend on other services.

public static IServiceCollection AddOptunaStorage(this IServiceCollection services, Func<IServiceProvider, BaseStorage> factory, ServiceLifetime lifetime = ServiceLifetime.Singleton)

Parameters

services IServiceCollection

The service collection to add to.

factory Func<IServiceProvider, BaseStorage>

Builds the storage from the resolved IServiceProvider.

lifetime ServiceLifetime

The registration lifetime; defaults to Singleton.

Returns

IServiceCollection

The same services, for chaining.

Exceptions

ArgumentNullException

services or factory is null.

AddOptunaStorage(IServiceCollection, string, ServiceLifetime)

Register the RDB storage an Optuna storage URL names (the string form of optuna.create_study(storage=...)): sqlite:///… through the OptunaSharp.Storage.Sqlite package, and postgresql://…, mysql://… and mariadb://… through OptunaSharp.Storage.EFCore. The application must reference the package that serves the URL's dialect; Core finds it by name.

public static IServiceCollection AddOptunaStorage(this IServiceCollection services, string storageUrl, ServiceLifetime lifetime = ServiceLifetime.Singleton)

Parameters

services IServiceCollection

The service collection to add to.

storageUrl string

A SQLAlchemy-style storage URL, resolved like GetStorage(string) resolves it, for example sqlite:///study.db or postgresql://user:password@host:5432/optuna.

lifetime ServiceLifetime

The registration lifetime; defaults to Singleton, so every study shares one connection that the container disposes at shutdown. Scoped opens a connection per scope and Transient one per resolution; the container disposes each when its scope ends.

Returns

IServiceCollection

The same services, for chaining.

Remarks

The registration is the one the serving package's own AddSqliteStorage(url) or AddEFCoreStorage(url) makes: the storage is registered as its concrete RDBStorage type and forwarded as BaseStorage, the container owns and disposes it, and every study the factory builds wraps it in its own CachedStorage. That differs from GetStorage(string), whose cache never disposes the connection.

The URL is checked when this method runs, so a malformed URL, an unknown dialect or a missing package fails at startup. The database is opened on first resolution, so an unreachable server fails then.

Journal and Redis journal storages have no URL form in Optuna. Register them with AddOptunaStorage(IServiceCollection, BaseStorage) or their package's Add…JournalStorage method.

Exceptions

ArgumentNullException

services or storageUrl is null.

ValueError

The URL starts with redis: Optuna removed RedisStorage in v3.1.0.

ArgumentException

The URL does not start with name:// (for example a bare file path), or it names a dialect SQLAlchemy does not know (for example postgres). The messages are SQLAlchemy's.

NotSupportedException

No OptunaSharp package serves the URL's dialect (oracle, mssql), or the application does not reference the package that does. The message starts with Optuna's ImportError text.

AddOptunaStudyFactory(IServiceCollection, Action<OptunaStudyOptions>?)

Register the IOptunaStudyFactory (and its OptunaStudyOptions) that composes the container's sampler / pruner / storage into studies. Idempotent — a second call is a no-op (it uses TryAdd), so the first configure wins; call it once at the composition root.

public static IServiceCollection AddOptunaStudyFactory(this IServiceCollection services, Action<OptunaStudyOptions>? configure = null)

Parameters

services IServiceCollection

The service collection to add to.

configure Action<OptunaStudyOptions>

Optional callback to set the default study shape (direction, name, load-if-exists).

Returns

IServiceCollection

The same services, for chaining.

Remarks

The factory is registered as Transient, so it resolves its sampler, pruner and storage from the provider that resolved it. Inside a request scope that is the scope: scoped registrations work, and are not captured by the root. A singleton consumer such as a hosted service gets the root provider and its singletons and transients. A singleton factory would always use the root, and then a scoped sampler or storage either throws "Cannot resolve scoped service from root provider" (under scope validation) or silently becomes an application-wide singleton.

Exceptions

ArgumentNullException

services is null.