diff --git a/Framework/Foundation/Foundation.csproj b/Framework/Foundation/Foundation.csproj index 58286b8..bd3f1a3 100644 --- a/Framework/Foundation/Foundation.csproj +++ b/Framework/Foundation/Foundation.csproj @@ -15,6 +15,7 @@ + diff --git a/Framework/Foundation/Lifecycles/Disposer.cs b/Framework/Foundation/Lifecycles/Disposer.cs new file mode 100644 index 0000000..1b1731e --- /dev/null +++ b/Framework/Foundation/Lifecycles/Disposer.cs @@ -0,0 +1,46 @@ +using System.Runtime.CompilerServices; +using System.Reactive.Disposables; + +namespace Toolkit.Framework.Foundation; + +public class Disposer : IDisposer +{ + private readonly ConditionalWeakTable subjects = new(); + + public void Add(object subject, params object[] objects) + { + CompositeDisposable disposables = subjects.GetOrCreateValue(subject); + foreach (IDisposable disposable in objects.OfType()) + { + disposables.Add(disposable); + } + } + + public TDisposable Replace(object subject, IDisposable disposer, TDisposable replacement) where TDisposable : IDisposable + { + CompositeDisposable disposables = subjects.GetOrCreateValue(subject); + if (disposer is not null) + { + disposables.Remove(disposer); + } + + disposables.Add(replacement); + return replacement; + } + public void Remove(object subject, IDisposable disposer) + { + CompositeDisposable disposables = subjects.GetOrCreateValue(subject); + if (disposer is not null) + { + disposables.Remove(disposer); + } + } + + public void Dispose(object subject) + { + if (subjects.TryGetValue(subject, out CompositeDisposable disposables)) + { + disposables.Dispose(); + } + } +} diff --git a/Framework/Foundation/Lifecycles/IDisposer.cs b/Framework/Foundation/Lifecycles/IDisposer.cs new file mode 100644 index 0000000..74226cd --- /dev/null +++ b/Framework/Foundation/Lifecycles/IDisposer.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Framework.Foundation; + +public interface IDisposer +{ + void Add(object subject, params object[] objects); + + void Remove(object subject, IDisposable disposer); + + void Dispose(object subject); +} diff --git a/Framework/Foundation/Lifecycles/Mediator.cs b/Framework/Foundation/Lifecycles/Mediator.cs index d0be017..5e79e62 100644 --- a/Framework/Foundation/Lifecycles/Mediator.cs +++ b/Framework/Foundation/Lifecycles/Mediator.cs @@ -1,12 +1,13 @@ using Microsoft.Extensions.DependencyInjection; -using System.Collections.Concurrent; +using System.Runtime.CompilerServices; namespace Toolkit.Framework.Foundation; public class Mediator : IMediator { private readonly IServiceProvider factory; - private readonly ConcurrentDictionary> subscriptions = new(); + + private readonly ConditionalWeakTable handlers = new(); public Mediator(IServiceProvider factory) { @@ -16,10 +17,13 @@ public class Mediator : IMediator public ValueTask Publish(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification { List> handlers = factory.GetServices>().ToList(); - - foreach (dynamic handler in subscriptions[typeof(TNotification)]) + + foreach (KeyValuePair handler in this.handlers) { - handlers.Add(handler); + if (handler.Key == typeof(TNotification)) + { + handlers.Add(handler.Value); + } } if (handlers.Count == 0) @@ -114,9 +118,9 @@ public class Mediator : IMediator return default; } - public void Subscribe(object subscriber) + public void Subscribe(object subject) { - Type[] interfaceTypes = subscriber.GetType().GetInterfaces(); + Type[] interfaceTypes = subject.GetType().GetInterfaces(); foreach (Type interfaceType in interfaceTypes.Where(x => x.IsGenericType)) { if (interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)) @@ -124,12 +128,7 @@ public class Mediator : IMediator if (interfaceType.GetGenericArguments() is { Length: 1 } arguments) { Type notificationType = arguments[0]; - - subscriptions.AddOrUpdate(notificationType, new HashSet { subscriber }, (type, hashSet) => - { - hashSet.Add(subscriber); - return hashSet; - }); + handlers.Add(notificationType, subject); } } }