-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dynamic delegate event handlers (#10)
* Add dynamic delegate event handlers * Update package-readme.md
- Loading branch information
Showing
12 changed files
with
630 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System.Collections.Generic; | ||
using M.EventBrokerSlim.DependencyInjection; | ||
|
||
namespace M.EventBrokerSlim; | ||
|
||
/// <summary> | ||
/// Allows managing of delegate event handlers at runtime. | ||
/// </summary> | ||
public interface IDynamicEventHandlers | ||
{ | ||
/// <summary> | ||
/// Adds one or more delegate handlers. | ||
/// </summary> | ||
/// <param name="builder">An instance of <see cref="DelegateHandlerRegistryBuilder"/> describing the handlers.</param> | ||
/// <returns><see cref="IDynamicHandlerClaimTicket"/> identifying added handlers.</returns> | ||
IDynamicHandlerClaimTicket Add(DelegateHandlerRegistryBuilder builder); | ||
|
||
/// <summary> | ||
/// Removes one or more delegate handlers by <see cref="IDynamicHandlerClaimTicket"/> | ||
/// </summary> | ||
/// <param name="claimTicket"><see cref="IDynamicHandlerClaimTicket"/> identifying handlers to remove.</param> | ||
void Remove(IDynamicHandlerClaimTicket claimTicket); | ||
|
||
/// <summary> | ||
/// Removes one or more delegate handlers by <see cref="IDynamicHandlerClaimTicket"/> | ||
/// </summary> | ||
/// <param name="claimTickets">Multiple <see cref="IDynamicHandlerClaimTicket"/> identifying handlers to remove.</param> | ||
void RemoveRange(IEnumerable<IDynamicHandlerClaimTicket> claimTickets); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace M.EventBrokerSlim; | ||
|
||
/// <summary> | ||
/// Identifies one or more delegate event handlers added by <see cref="IDynamicEventHandlers"/> | ||
/// </summary> | ||
public interface IDynamicHandlerClaimTicket | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Threading; | ||
using M.EventBrokerSlim.DependencyInjection; | ||
|
||
namespace M.EventBrokerSlim.Internal; | ||
|
||
internal sealed class DynamicEventHandlers : IDynamicEventHandlers | ||
{ | ||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); | ||
private readonly Dictionary<Type, ImmutableList<DelegateHandlerDescriptor>> _handlers = new Dictionary<Type, ImmutableList<DelegateHandlerDescriptor>>(); | ||
|
||
public IDynamicHandlerClaimTicket Add(DelegateHandlerRegistryBuilder builder) | ||
{ | ||
try | ||
{ | ||
_semaphore.Wait(); | ||
var claimTicket = new DynamicHandlerClaimTicket(Guid.NewGuid()); | ||
foreach(DelegateHandlerDescriptor handler in builder.HandlerDescriptors) | ||
{ | ||
if(!_handlers.TryGetValue(handler.EventType, out ImmutableList<DelegateHandlerDescriptor>? value)) | ||
{ | ||
value = ImmutableList<DelegateHandlerDescriptor>.Empty; | ||
_handlers[handler.EventType] = value; | ||
} | ||
|
||
handler.ClaimTicket = claimTicket; | ||
_handlers[handler.EventType] = value.Add(handler); | ||
} | ||
|
||
return claimTicket; | ||
} | ||
finally | ||
{ | ||
_semaphore.Release(); | ||
} | ||
} | ||
|
||
public void Remove(IDynamicHandlerClaimTicket claimTicket) | ||
{ | ||
try | ||
{ | ||
_semaphore.Wait(); | ||
foreach(var key in _handlers.Keys) | ||
{ | ||
_handlers[key] = _handlers[key].RemoveAll(x => | ||
{ | ||
if(x.ClaimTicket is null) | ||
{ | ||
return true; | ||
} | ||
if(x.ClaimTicket.Equals(claimTicket)) | ||
{ | ||
x.ClaimTicket = null; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
} | ||
} | ||
finally | ||
{ | ||
_semaphore.Release(); | ||
} | ||
} | ||
|
||
public void RemoveRange(IEnumerable<IDynamicHandlerClaimTicket> claimTickets) | ||
{ | ||
try | ||
{ | ||
_semaphore.Wait(); | ||
var claimTicketSet = new HashSet<IDynamicHandlerClaimTicket>(claimTickets); | ||
foreach(var key in _handlers.Keys) | ||
{ | ||
_handlers[key] = _handlers[key].RemoveAll(x => | ||
{ | ||
if(x.ClaimTicket is null) | ||
{ | ||
return true; | ||
} | ||
if(claimTicketSet.Contains(x.ClaimTicket)) | ||
{ | ||
x.ClaimTicket = null; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
} | ||
} | ||
finally | ||
{ | ||
_semaphore.Release(); | ||
} | ||
} | ||
|
||
internal ImmutableList<DelegateHandlerDescriptor>? GetDelegateHandlerDescriptors(Type eventType) | ||
{ | ||
_ = _handlers.TryGetValue(eventType, out ImmutableList<DelegateHandlerDescriptor>? handlerDescriptors); | ||
return handlerDescriptors; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
using System; | ||
|
||
namespace M.EventBrokerSlim.Internal; | ||
|
||
internal sealed record DynamicHandlerClaimTicket(Guid Id) : IDynamicHandlerClaimTicket; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.