Added Disposer

This commit is contained in:
Daniel Clark
2022-12-18 20:23:44 +00:00
parent 06ca2fbc8b
commit e9dd86e0e0
4 changed files with 69 additions and 13 deletions
+1
View File
@@ -15,6 +15,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,46 @@
using System.Runtime.CompilerServices;
using System.Reactive.Disposables;
namespace Toolkit.Framework.Foundation;
public class Disposer : IDisposer
{
private readonly ConditionalWeakTable<object, CompositeDisposable> subjects = new();
public void Add(object subject, params object[] objects)
{
CompositeDisposable disposables = subjects.GetOrCreateValue(subject);
foreach (IDisposable disposable in objects.OfType<IDisposable>())
{
disposables.Add(disposable);
}
}
public TDisposable Replace<TDisposable>(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();
}
}
}
@@ -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);
}
+12 -13
View File
@@ -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<Type, HashSet<dynamic>> subscriptions = new();
private readonly ConditionalWeakTable<Type, dynamic> handlers = new();
public Mediator(IServiceProvider factory)
{
@@ -16,10 +17,13 @@ public class Mediator : IMediator
public ValueTask Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification
{
List<INotificationHandler<TNotification>> handlers = factory.GetServices<INotificationHandler<TNotification>>().ToList();
foreach (dynamic handler in subscriptions[typeof(TNotification)])
foreach (KeyValuePair<Type, dynamic> 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<dynamic> { subscriber }, (type, hashSet) =>
{
hashSet.Add(subscriber);
return hashSet;
});
handlers.Add(notificationType, subject);
}
}
}