This commit is contained in:
TheXamlGuy
2024-05-31 14:07:35 +01:00
parent 041dd81717
commit 8f1a3252c6
10 changed files with 112 additions and 41 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class AggerateAttribute(object key, public class AggerateAttribute(Type type, object key,
AggerateMode mode = AggerateMode.Reset) : NotificationAttribute(key) AggerateMode mode = AggerateMode.Reset) : NotificationAttribute(type, key)
{ {
public AggerateMode Mode => mode; public AggerateMode Mode => mode;
} }
+1 -1
View File
@@ -13,7 +13,7 @@ public class AppService(IEnumerable<IInitializer> initializers,
await initializer.Initialize(); await initializer.Initialize();
} }
publisher.Publish<StartedEventArgs>(cancellationToken); publisher.Publish<StartedEventArgs>();
} }
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
-1
View File
@@ -7,7 +7,6 @@ public class HandlerProvider(SubscriptionCollection subscriptions) :
object? key = null) object? key = null)
{ {
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}"; string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}";
var d = subscriptions;
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers)) if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
{ {
foreach (WeakReference weakRef in subscribers.ToArray()) foreach (WeakReference weakRef in subscribers.ToArray())
@@ -32,7 +32,15 @@ public static class IServiceCollectionExtensions
} }
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services, public static IServiceCollection AddHandler<THandler>(this IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Transient) string key)
where THandler : IHandler
{
return AddHandler<THandler>(services, ServiceLifetime.Transient, key);
}
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Transient,
string? key = null)
where THandler : IHandler where THandler : IHandler
{ {
if (typeof(THandler).GetInterfaces() is Type[] contracts) if (typeof(THandler).GetInterfaces() is Type[] contracts)
@@ -47,15 +55,35 @@ public static class IServiceCollectionExtensions
Type wrapperType = typeof(NotificationHandlerWrapper<>) Type wrapperType = typeof(NotificationHandlerWrapper<>)
.MakeGenericType(notificationType); .MakeGenericType(notificationType);
if (key is not null)
{
services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>)
.MakeGenericType(notificationType), key, typeof(THandler), lifetime));
}
else
{
services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>) services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>)
.MakeGenericType(notificationType), typeof(THandler), lifetime)); .MakeGenericType(notificationType), typeof(THandler), lifetime));
}
if (key is not null)
{
services.Add(new ServiceDescriptor(wrapperType, key, (provider, key) =>
provider.GetService<IServiceFactory>()?.Create(wrapperType,
provider.GetRequiredKeyedService(typeof(INotificationHandler<>).MakeGenericType(notificationType), key),
provider.GetServices(typeof(IPipelineBehaviour<>)
.MakeGenericType(notificationType)))!, lifetime));
}
else
{
services.Add(new ServiceDescriptor(wrapperType, provider => services.Add(new ServiceDescriptor(wrapperType, provider =>
provider.GetService<IServiceFactory>()?.Create(wrapperType, provider.GetService<IServiceFactory>()?.Create(wrapperType,
provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)), provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)),
provider.GetServices(typeof(IPipelineBehaviour<>) provider.GetServices(typeof(IPipelineBehaviour<>)
.MakeGenericType(notificationType)))!, lifetime)); .MakeGenericType(notificationType)))!, lifetime));
} }
}
if (contract.Name == typeof(IHandler<,>).Name && if (contract.Name == typeof(IHandler<,>).Name &&
contract.GetGenericArguments() is { Length: 2 } handlerArguments) contract.GetGenericArguments() is { Length: 2 } handlerArguments)
+5 -2
View File
@@ -1,7 +1,10 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public class NotificationAttribute(object key) : Attribute [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class NotificationAttribute(Type type, object key) : Attribute
{ {
public Type Type => type;
public object Key => key; public object Key => key;
} }
+13 -1
View File
@@ -22,11 +22,23 @@ public static class ObjectExtensions
where TAttribute : Attribute where TAttribute : Attribute
{ {
Type type = obj.GetType(); Type type = obj.GetType();
if (type.GetAttribute<TAttribute>() is TAttribute attribute) if (type.GetCustomAttribute<TAttribute>(true) is TAttribute attribute)
{ {
return attribute; return attribute;
} }
return null; return null;
} }
public static IEnumerable<TAttribute> GetAttributes<TAttribute>(this object obj)
where TAttribute : Attribute
{
Type type = obj.GetType();
if (type.GetCustomAttributes<TAttribute>(true) is IEnumerable<TAttribute> attributes)
{
return attributes;
}
return Enumerable.Empty<TAttribute>();
}
} }
+29 -3
View File
@@ -157,6 +157,8 @@ public partial class ObservableCollection<TItem> :
{ {
int index = collection.Count; int index = collection.Count;
InsertItem(index, item); InsertItem(index, item);
UpdateSelection(item);
} }
public void Add(object item) public void Add(object item)
@@ -399,12 +401,17 @@ public partial class ObservableCollection<TItem> :
{ {
T? item = Factory.Create<T>(parameters); T? item = Factory.Create<T>(parameters);
InsertItem(index, item); InsertItem(index, item);
UpdateSelection(item);
return item; return item;
} }
public void Insert(int index, TItem item) => public void Insert(int index,
TItem item)
{
InsertItem(index, item); InsertItem(index, item);
UpdateSelection(item);
}
void IList.Insert(int index, void IList.Insert(int index,
object? value) object? value)
@@ -412,6 +419,7 @@ public partial class ObservableCollection<TItem> :
if (value is TItem item) if (value is TItem item)
{ {
Insert(index, item); Insert(index, item);
UpdateSelection(item);
} }
} }
@@ -424,8 +432,27 @@ public partial class ObservableCollection<TItem> :
TItem item = this[oldIndex]; TItem item = this[oldIndex];
bool moveSelection = false;
if (item is ISelectable oldSelection)
{
if (oldSelection.Selected)
{
moveSelection = true;
SelectedItem = default;
}
}
RemoveItem(oldIndex); RemoveItem(oldIndex);
Insert(newIndex, item); InsertItem(newIndex, item);
if (moveSelection)
{
if (item is ISelectable newSelection)
{
newSelection.Selected = true;
dispatcher.Invoke(() => SelectedItem = item);
}
}
return true; return true;
} }
@@ -535,7 +562,6 @@ public partial class ObservableCollection<TItem> :
} }
})); }));
UpdateSelection(item);
collection.Insert(index > Count ? Count : index, item); collection.Insert(index > Count ? Count : index, item);
} }
+3 -1
View File
@@ -29,7 +29,9 @@ public class Publisher(IHandlerProvider handlerProvider,
Type handlerType = typeof(NotificationHandlerWrapper<>) Type handlerType = typeof(NotificationHandlerWrapper<>)
.MakeGenericType(notificationType); .MakeGenericType(notificationType);
List<object?> handlers = serviceProvider.GetServices(handlerType).ToList(); List<object?> handlers = key is not null ? serviceProvider.GetKeyedServices(handlerType, key).ToList() :
serviceProvider.GetServices(handlerType).ToList();
foreach (object? handler in handlerProvider.Get(notificationType, key)) foreach (object? handler in handlerProvider.Get(notificationType, key))
{ {
handlers.Add(handler); handlers.Add(handler);
+23 -5
View File
@@ -9,11 +9,14 @@ public class Subscription(SubscriptionCollection subscriptions,
public void Add(object subscriber) public void Add(object subscriber)
{ {
Type handlerType = subscriber.GetType(); Type handlerType = subscriber.GetType();
object? key = GetKeyFromHandler(subscriber);
IDictionary<Type, object> keys = GetKeysFromHandler(subscriber);
foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
{ {
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
{ {
keys.TryGetValue(argumentType, out object? key);
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}"; string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}";
subscriptions.AddOrUpdate(subscriptionKey, _ => new List<WeakReference> { new(subscriber) }, (_, collection) => subscriptions.AddOrUpdate(subscriptionKey, _ => new List<WeakReference> { new(subscriber) }, (_, collection) =>
{ {
@@ -29,11 +32,13 @@ public class Subscription(SubscriptionCollection subscriptions,
public void Remove(object subscriber) public void Remove(object subscriber)
{ {
Type handlerType = subscriber.GetType(); Type handlerType = subscriber.GetType();
object? key = GetKeyFromHandler(subscriber); IDictionary<Type, object> keys = GetKeysFromHandler(subscriber);
foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
{ {
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
{ {
keys.TryGetValue(argumentType, out object? key);
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}"; string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}";
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers)) if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
{ {
@@ -69,9 +74,22 @@ public class Subscription(SubscriptionCollection subscriptions,
} }
} }
private object? GetKeyFromHandler(object handler) => //private object? GetKeyFromHandler(object handler) =>
handler.GetAttribute<NotificationAttribute>() is NotificationAttribute attribute // handler.GetAttribute<NotificationAttribute>() is NotificationAttribute attribute
? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key : null; // ? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key : null;
private IDictionary<Type, object> GetKeysFromHandler(object handler)
{
Dictionary<Type, object> keys = [];
foreach (NotificationAttribute attribute in handler.GetAttributes<NotificationAttribute>())
{
keys.Add(attribute.Type, attribute.Key);
}
return keys;
}
private IEnumerable<Type> GetHandlerInterfaces(Type handlerType) => private IEnumerable<Type> GetHandlerInterfaces(Type handlerType) =>
handlerType.GetInterfaces().Where(interfaceType => handlerType.GetInterfaces().Where(interfaceType =>
-17
View File
@@ -1,17 +0,0 @@
using System.Reflection;
namespace Toolkit.Foundation;
public static class TypeExtensions
{
public static TAttribute? GetAttribute<TAttribute>(this Type type)
where TAttribute : Attribute
{
if (type.GetCustomAttribute<TAttribute>() is TAttribute attribute)
{
return attribute;
}
return null;
}
}