Added Disposer
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="7.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||||
|
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</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);
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using System.Collections.Concurrent;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Toolkit.Framework.Foundation;
|
namespace Toolkit.Framework.Foundation;
|
||||||
|
|
||||||
public class Mediator : IMediator
|
public class Mediator : IMediator
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider factory;
|
private readonly IServiceProvider factory;
|
||||||
private readonly ConcurrentDictionary<Type, HashSet<dynamic>> subscriptions = new();
|
|
||||||
|
private readonly ConditionalWeakTable<Type, dynamic> handlers = new();
|
||||||
|
|
||||||
public Mediator(IServiceProvider factory)
|
public Mediator(IServiceProvider factory)
|
||||||
{
|
{
|
||||||
@@ -17,9 +18,12 @@ public class Mediator : IMediator
|
|||||||
{
|
{
|
||||||
List<INotificationHandler<TNotification>> handlers = factory.GetServices<INotificationHandler<TNotification>>().ToList();
|
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)
|
if (handlers.Count == 0)
|
||||||
@@ -114,9 +118,9 @@ public class Mediator : IMediator
|
|||||||
return default;
|
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))
|
foreach (Type interfaceType in interfaceTypes.Where(x => x.IsGenericType))
|
||||||
{
|
{
|
||||||
if (interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>))
|
if (interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>))
|
||||||
@@ -124,12 +128,7 @@ public class Mediator : IMediator
|
|||||||
if (interfaceType.GetGenericArguments() is { Length: 1 } arguments)
|
if (interfaceType.GetGenericArguments() is { Length: 1 } arguments)
|
||||||
{
|
{
|
||||||
Type notificationType = arguments[0];
|
Type notificationType = arguments[0];
|
||||||
|
handlers.Add(notificationType, subject);
|
||||||
subscriptions.AddOrUpdate(notificationType, new HashSet<dynamic> { subscriber }, (type, hashSet) =>
|
|
||||||
{
|
|
||||||
hashSet.Add(subscriber);
|
|
||||||
return hashSet;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user