Skip to content

Commit

Permalink
Core: ServiceRegistry, GetOrCreate<T> and Remove(instance)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eideren committed Jan 21, 2025
1 parent 5359f32 commit e830c34
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
11 changes: 11 additions & 0 deletions sources/core/Stride.Core/IService.cs
Original file line number Diff line number Diff line change
@@ -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);
}
16 changes: 16 additions & 0 deletions sources/core/Stride.Core/IServiceRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public interface IServiceRegistry
/// <summary>
/// Gets the service object of the specified type.
/// </summary>
/// <remarks>The generic type provided must match the generic type of your initial call to <see cref="AddService{T}"/></remarks>
/// <typeparam name="T">The type of the service to retrieve.</typeparam>
/// <returns>A service of the requested type, or [null] if not found.</returns>
[CanBeNull]
Expand All @@ -60,7 +61,22 @@ public interface IServiceRegistry
/// <summary>
/// Removes the object providing a specified service.
/// </summary>
/// <remarks>The generic type provided must match the generic type of your initial call to <see cref="AddService{T}"/></remarks>
/// <typeparam name="T">The type of the service to remove.</typeparam>
void RemoveService<T>() where T : class;

/// <summary>
/// Removes the following object from services if it was registered as one.
/// </summary>
/// <remarks>The generic type provided must match the generic type of your initial call to <see cref="AddService{T}"/></remarks>
/// <returns>True if the argument was a service, false otherwise</returns>
/// <typeparam name="T">The type of the service to remove.</typeparam>
bool RemoveService<T>([NotNull] T serviceObject) where T : class;

/// <summary>
/// Gets the service object of the specified type, create one if it didn't exist before.
/// </summary>
/// <typeparam name="T">The type of the service to retrieve.</typeparam>
[NotNull] T GetOrCreate<T>() where T : class, IService;
}
}
39 changes: 35 additions & 4 deletions sources/core/Stride.Core/ServiceRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,8 @@ public void AddService<T>(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));
}
Expand All @@ -91,13 +90,45 @@ public void RemoveService<T>()
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));
}

/// <inheritdoc />
public bool RemoveService<T>(T serviceObject) where T : class
{
lock (registeredService)
{
if (ReferenceEquals(GetService<T>(), serviceObject))
{
RemoveService<T>();
return true;
}
else
{
return false;
}
}
}

/// <inheritdoc />
public T GetOrCreate<T>() where T : class, IService
{
lock (registeredService)
{
var t = GetService<T>();
if (t is null)
{
t = (T)T.NewInstance(this);
AddService(t);
}

return t;
}
}

private void OnServiceAdded(ServiceEventArgs e)
{
ServiceAdded?.Invoke(this, e);
Expand Down

0 comments on commit e830c34

Please sign in to comment.