diff --git a/sources/core/Stride.Core/IService.cs b/sources/core/Stride.Core/IService.cs
new file mode 100644
index 0000000000..e57ee1b0b9
--- /dev/null
+++ b/sources/core/Stride.Core/IService.cs
@@ -0,0 +1,11 @@
+// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net)
+// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
+
+using Stride.Core.Annotations;
+
+namespace Stride.Core;
+
+public interface IService
+{
+ [NotNull] public static abstract IService NewInstance([NotNull] IServiceRegistry services);
+}
diff --git a/sources/core/Stride.Core/IServiceRegistry.cs b/sources/core/Stride.Core/IServiceRegistry.cs
index 06340c94b0..30f1decf47 100644
--- a/sources/core/Stride.Core/IServiceRegistry.cs
+++ b/sources/core/Stride.Core/IServiceRegistry.cs
@@ -52,6 +52,7 @@ public interface IServiceRegistry
///
/// Gets the service object of the specified type.
///
+ /// The generic type provided must match the generic type of your initial call to
/// The type of the service to retrieve.
/// A service of the requested type, or [null] if not found.
[CanBeNull]
@@ -60,7 +61,22 @@ public interface IServiceRegistry
///
/// Removes the object providing a specified service.
///
+ /// The generic type provided must match the generic type of your initial call to
/// The type of the service to remove.
void RemoveService() where T : class;
+
+ ///
+ /// Removes the following object from services if it was registered as one.
+ ///
+ /// The generic type provided must match the generic type of your initial call to
+ /// True if the argument was a service, false otherwise
+ /// The type of the service to remove.
+ bool RemoveService([NotNull] T serviceObject) where T : class;
+
+ ///
+ /// Gets the service object of the specified type, create one if it didn't exist before.
+ ///
+ /// The type of the service to retrieve.
+ [NotNull] T GetOrCreate() where T : class, IService;
}
}
diff --git a/sources/core/Stride.Core/ServiceRegistry.cs b/sources/core/Stride.Core/ServiceRegistry.cs
index 4cde923327..8ce8348477 100644
--- a/sources/core/Stride.Core/ServiceRegistry.cs
+++ b/sources/core/Stride.Core/ServiceRegistry.cs
@@ -72,9 +72,8 @@ public void AddService(T service)
var type = typeof(T);
lock (registeredService)
{
- if (registeredService.ContainsKey(type))
+ if (registeredService.TryAdd(type, service) == false)
throw new ArgumentException("Service is already registered with this type", nameof(type));
- registeredService.Add(type, service);
}
OnServiceAdded(new ServiceEventArgs(type, service));
}
@@ -91,13 +90,45 @@ public void RemoveService()
object oldService;
lock (registeredService)
{
- if (registeredService.TryGetValue(type, out oldService))
- registeredService.Remove(type);
+ registeredService.Remove(type, out oldService);
}
if (oldService != null)
OnServiceRemoved(new ServiceEventArgs(type, oldService));
}
+ ///
+ public bool RemoveService(T serviceObject) where T : class
+ {
+ lock (registeredService)
+ {
+ if (ReferenceEquals(GetService(), serviceObject))
+ {
+ RemoveService();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ ///
+ public T GetOrCreate() where T : class, IService
+ {
+ lock (registeredService)
+ {
+ var t = GetService();
+ if (t is null)
+ {
+ t = (T)T.NewInstance(this);
+ AddService(t);
+ }
+
+ return t;
+ }
+ }
+
private void OnServiceAdded(ServiceEventArgs e)
{
ServiceAdded?.Invoke(this, e);