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
servicesIServiceCollectionThe service collection to add to.
prunerBasePrunerThe pruner instance shared by every study built from this container.
Returns
- IServiceCollection
The same
services, for chaining.
Exceptions
- ArgumentNullException
servicesorprunerisnull.
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
servicesIServiceCollectionThe service collection to add to.
factoryFunc<IServiceProvider, BasePruner>Builds the pruner from the resolved IServiceProvider.
lifetimeServiceLifetimeThe 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
servicesorfactoryisnull.
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
servicesIServiceCollectionThe service collection to add to.
samplerBaseSamplerThe sampler instance shared by every study built from this container.
Returns
- IServiceCollection
The same
services, for chaining.
Exceptions
- ArgumentNullException
servicesorsamplerisnull.
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
servicesIServiceCollectionThe service collection to add to.
factoryFunc<IServiceProvider, BaseSampler>Builds the sampler from the resolved IServiceProvider.
lifetimeServiceLifetimeThe 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
servicesorfactoryisnull.
AddOptunaStorage(IServiceCollection, BaseStorage)
Register a pre-built storage as the application's BaseStorage singleton.
public static IServiceCollection AddOptunaStorage(this IServiceCollection services, BaseStorage storage)
Parameters
servicesIServiceCollectionThe service collection to add to.
storageBaseStorageThe storage instance shared by every study built from this container.
Returns
- IServiceCollection
The same
services, for chaining.
Exceptions
- ArgumentNullException
servicesorstorageisnull.
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
servicesIServiceCollectionThe service collection to add to.
factoryFunc<IServiceProvider, BaseStorage>Builds the storage from the resolved IServiceProvider.
lifetimeServiceLifetimeThe registration lifetime; defaults to Singleton.
Returns
- IServiceCollection
The same
services, for chaining.
Exceptions
- ArgumentNullException
servicesorfactoryisnull.
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
servicesIServiceCollectionThe service collection to add to.
storageUrlstringA SQLAlchemy-style storage URL, resolved like GetStorage(string) resolves it, for example
sqlite:///study.dborpostgresql://user:password@host:5432/optuna.lifetimeServiceLifetimeThe 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
servicesorstorageUrlisnull.- 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 examplepostgres). 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'sImportErrortext.
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
servicesIServiceCollectionThe service collection to add to.
configureAction<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
servicesisnull.