added Disposer

This commit is contained in:
TheXamlGuy
2024-01-10 21:07:31 +00:00
parent e742b97b44
commit 7ccfedb5e2
5 changed files with 104 additions and 5 deletions
+1
View File
@@ -7,5 +7,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+1
View File
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using System;
namespace Hyperbar; namespace Hyperbar;
+81
View File
@@ -0,0 +1,81 @@
using System.Runtime.CompilerServices;
using System.Reactive.Disposables;
using System.Collections;
namespace Hyperbar;
public class Disposer :
IDisposer
{
private readonly ConditionalWeakTable<object, CompositeDisposable> subjects = [];
public void Add(object subject,
params object[] objects)
{
CompositeDisposable disposables = subjects.GetOrCreateValue(subject);
foreach (IDisposable disposable in objects.OfType<IDisposable>())
{
disposables.Add(disposable);
}
foreach (object notDisposable in objects.Where(x => x is not IDisposable))
{
disposables.Add(Disposable.Create(() => FromNotDisposable(notDisposable)));
}
}
private void FromNotDisposable(object target)
{
if (target is IEnumerable enumerableTarget)
{
foreach (object? item in enumerableTarget)
{
FromNotDisposable(item);
}
}
if (target is IDisposable disposableTarget)
{
disposableTarget.Dispose();
}
if (target is not IDisposable)
{
Dispose(target);
}
}
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();
}
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace Hyperbar;
public interface IDisposer
{
void Add(object subject,
params object[] objects);
TDisposable Replace<TDisposable>(object subject,
IDisposable disposer,
TDisposable replacement) where TDisposable : IDisposable;
void Remove(object subject,
IDisposable disposer);
void Dispose(object subject);
}
+5 -5
View File
@@ -6,7 +6,7 @@ namespace Hyperbar;
public class Mediator(IServiceProvider provider) : public class Mediator(IServiceProvider provider) :
IMediator IMediator
{ {
private readonly List<KeyValuePair<Type, dynamic>> addedHandlers = []; private readonly ConditionalWeakTable<dynamic, Type> subjects = [];
public ValueTask PublishAsync<TNotification>(TNotification notification, public ValueTask PublishAsync<TNotification>(TNotification notification,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
@@ -16,11 +16,11 @@ public class Mediator(IServiceProvider provider) :
List<INotificationHandler<TNotification>> handlers = List<INotificationHandler<TNotification>> handlers =
provider.GetServices<INotificationHandler<TNotification>>().ToList(); provider.GetServices<INotificationHandler<TNotification>>().ToList();
foreach (KeyValuePair<Type, dynamic> handler in addedHandlers) foreach (KeyValuePair<dynamic, Type> handler in subjects)
{ {
if (handler.Key == typeof(TNotification)) if (handler.Value == typeof(TNotification))
{ {
handlers.Add(handler.Value); handlers.Add(handler.Key);
} }
} }
@@ -78,7 +78,7 @@ public class Mediator(IServiceProvider provider) :
if (interfaceType.GetGenericArguments() is { Length: 1 } arguments) if (interfaceType.GetGenericArguments() is { Length: 1 } arguments)
{ {
Type notificationType = arguments[0]; Type notificationType = arguments[0];
addedHandlers.Add(new KeyValuePair<Type, dynamic>(notificationType, subject)); subjects.Add(subject, notificationType);
} }
} }
} }