Skip to content
One Last Click Docs

Service Collection builder

ServicesCollectionBuilder is used to register services and build a ServiceCollection from them.

It supports registering:

  • Existing service instances
  • Concrete types
  • Interface/type pairs
  • Services discovered from a GameObject
  • Services contained in a Scene
  • Services exposed through IServiceRegisterer

Managed services implementing IService are automatically tracked so that the resulting ServiceCollection can manage their lifecycle.

public ServiceCollection Build()

Creates a new ServiceCollection containing all services currently registered with the builder.

A ServiceCollection containing the registered service instances and managed services.

ServicesCollectionBuilder builder = new ServicesCollectionBuilder();
builder.Register<IMyService, MyService>();
ServiceCollection services = builder.Build();

public void RegisterGameObject(GameObject gameObject)

Registers services found on a GameObject and its children.

The method performs two operations:

  1. Finds all components implementing IService on the supplied GameObject and its children, including inactive objects, and registers them as managed services.
  2. Finds all IServiceRegisterer components directly attached to the supplied GameObject and allows them to register additional services with this builder.

IService components are discovered using GetComponentsInChildren<IService>(true).

IServiceRegisterer components are only searched for on the supplied GameObject; their children are not searched for IServiceRegisterer components.

Parameter Type Description
gameObject GameObject The root GameObject to scan for services.
builder.RegisterGameObject(gameObject);

A typical Unity setup might look like:

GameObject
├── AudioService → IService
├── SaveService → IService
└── UI
└── UIService → IService

All three IService components are discovered, including services on inactive child objects.


public void Register(object service, params Type[] types)

Registers an existing service instance against one or more types.

The supplied service must be assignable to every type passed in types. If it is not, an ArgumentException is thrown.

If the supplied instance implements IService, it is also added to the collection of managed services.

Parameter Type Description
service object The service instance to register.
types Type[] The types through which the service should be registered.

ArgumentException

Thrown when the service is not assignable to one of the supplied types.

MyService service = new MyService();
builder.Register(
service,
typeof(IMyService),
typeof(MyService)
);

The same instance can then be resolved through either registered type.

Note: Registration uses the type itself as the dictionary key. Registering another service against an already registered type throws because duplicate registrations are not permitted.


public void Register<TI, T>()
where T : TI, new()

Creates a new instance of T and registers it as both TI and T.

T must:

  • Implement or inherit from TI
  • Have a parameterless constructor

This is a convenience overload equivalent to creating the instance manually and passing it to Register<TI, T>(T service).

Parameter Constraint Description
TI — The interface or base type used for registration.
T TI, new() The concrete service type to instantiate.
builder.Register<IMyService, MyService>();

This is equivalent to:

MyService service = new MyService();
builder.Register<IMyService, MyService>(service);

public void Register<TI, T>(T service)
where T : TI

Registers an existing T instance as both TI and T.

Unlike the parameterless overload, this allows the service instance to be constructed manually.

Parameter Constraint Description
TI — The interface or base type used for registration.
T TI The concrete service type.
Parameter Type Description
service T The service instance to register.
MyService service = new MyService();
builder.Register<IMyService, MyService>(service);

The instance is registered under both:

IMyService
MyService

public void Register<T>(T service)

Registers an existing service instance using its concrete type.

Parameter Description
T The type of the service instance.
Parameter Type Description
service T The service instance to register.
MyService service = new MyService();
builder.Register(service);

The service is registered as:

MyService

If MyService implements IService, it is also tracked as a managed service.


public void Register<T>()
where T : new()

Creates a new instance of T and registers it using its concrete type.

T must have a parameterless constructor.

Parameter Constraint Description
T new() The service type to instantiate.
builder.Register<MyService>();

This is equivalent to:

builder.Register(new MyService());

public void RegisterSceneServices(Scene scene)

Registers services from every root GameObject in a Unity scene.

Each root GameObject is passed to RegisterGameObject.

This means IService components are discovered throughout the complete hierarchy of every root object in the scene.

IServiceRegisterer components are processed according to the behaviour of RegisterGameObject.

Parameter Type Description
scene Scene The Unity scene whose root objects should be scanned.
Scene scene = SceneManager.GetActiveScene();
builder.RegisterSceneServices(scene);

This is useful when services are defined as components in a scene rather than registered manually.


public bool TryGet(Type type, out object instance)

Attempts to retrieve a registered service using its registered type.

This method does not throw when the type has not been registered.

Parameter Type Description
type Type The registered type to look up.
instance object The registered service instance, if found.

true if a service was registered for the specified type; otherwise false.

if (builder.TryGet(typeof(IMyService), out object instance) == true)
{
IMyService service = (IMyService)instance;
}

A service is considered managed when its instance implements IService.

For example:

public class MyService : IService
{
}

When registered, the same instance is automatically added to the builder’s managed service list.

MyService service = new MyService();
builder.Register(service);

Managed services are only added once. Registering the same instance multiple times does not create duplicate managed-service entries.

The managed-service list is passed to the resulting ServiceCollection when Build is called.

The following registrations automatically become managed when the instance implements IService:

builder.Register(service);
builder.Register<MyService>(service);
builder.Register<IMyService, MyService>(service);
builder.RegisterGameObject(gameObject);
builder.RegisterSceneServices(scene);

RegisterGameObject also supports components implementing IServiceRegisterer.

A registerer can register additional services through the builder:

public class MyServiceRegisterer : MonoBehaviour, IServiceRegisterer
{
public void RegisterServices(ServicesCollectionBuilder builder)
{
builder.Register<IMyService, MyService>();
}
}

When the containing GameObject is registered:

builder.RegisterGameObject(gameObject);

the registerer’s RegisterServices method is invoked automatically.

This allows registration logic to live alongside Unity components that own or configure the services.


Method Creates instance Registers as Managed if IService
Register(object, params Type[]) No Supplied types Yes
Register<TI, T>() Yes TI, T Yes
Register<TI, T>(T) No TI, T Yes
Register<T>(T) No T Yes
Register<T>() Yes T Yes
RegisterGameObject(GameObject) No Discovered/registerer-defined types Yes
RegisterSceneServices(Scene) No Discovered/registerer-defined types Yes

A complete setup might look like:

ServicesCollectionBuilder builder = new ServicesCollectionBuilder();
builder.Register<ILogger, GameLogger>();
builder.Register(new SaveService());
builder.RegisterSceneServices(SceneManager.GetActiveScene());
ServiceCollection services = builder.Build();

The resulting ServiceCollection contains all manually registered services as well as services discovered from the scene.

  • A type can only be registered once.
  • Registering a type that already exists throws an ArgumentException due to duplicate dictionary keys.
  • Register(object, params Type[]) validates that the service is assignable to every supplied type.
  • Services implementing IService are automatically tracked as managed services.
  • The same managed service instance is only tracked once.
  • RegisterGameObject searches child objects for IService, including inactive children.
  • RegisterGameObject only searches the supplied object itself for IServiceRegisterer.
  • RegisterSceneServices processes every root GameObject in the scene.
  • Build() creates a ServiceCollection from the registrations accumulated so far.
  • The builder itself does not expose a typed Get<T>(); use TryGet(Type, out object) when querying the builder directly.