wip
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class AggerateAttribute(object key,
|
||||
AggerateMode mode = AggerateMode.Reset) : NotificationAttribute(key)
|
||||
public class AggerateAttribute(Type type, object key,
|
||||
AggerateMode mode = AggerateMode.Reset) : NotificationAttribute(type, key)
|
||||
{
|
||||
public AggerateMode Mode => mode;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class AppService(IEnumerable<IInitializer> initializers,
|
||||
await initializer.Initialize();
|
||||
}
|
||||
|
||||
publisher.Publish<StartedEventArgs>(cancellationToken);
|
||||
publisher.Publish<StartedEventArgs>();
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
@@ -7,7 +7,6 @@ public class HandlerProvider(SubscriptionCollection subscriptions) :
|
||||
object? key = null)
|
||||
{
|
||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}";
|
||||
var d = subscriptions;
|
||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
||||
{
|
||||
foreach (WeakReference weakRef in subscribers.ToArray())
|
||||
|
||||
@@ -32,7 +32,15 @@ public static class IServiceCollectionExtensions
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (typeof(THandler).GetInterfaces() is Type[] contracts)
|
||||
@@ -47,15 +55,35 @@ public static class IServiceCollectionExtensions
|
||||
Type wrapperType = typeof(NotificationHandlerWrapper<>)
|
||||
.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<>)
|
||||
.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 =>
|
||||
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
||||
provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)),
|
||||
provider.GetServices(typeof(IPipelineBehaviour<>)
|
||||
.MakeGenericType(notificationType)))!, lifetime));
|
||||
}
|
||||
}
|
||||
|
||||
if (contract.Name == typeof(IHandler<,>).Name &&
|
||||
contract.GetGenericArguments() is { Length: 2 } handlerArguments)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
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;
|
||||
}
|
||||
@@ -22,11 +22,23 @@ public static class ObjectExtensions
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
Type type = obj.GetType();
|
||||
if (type.GetAttribute<TAttribute>() is TAttribute attribute)
|
||||
if (type.GetCustomAttribute<TAttribute>(true) is TAttribute attribute)
|
||||
{
|
||||
return attribute;
|
||||
}
|
||||
|
||||
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>();
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,8 @@ public partial class ObservableCollection<TItem> :
|
||||
{
|
||||
int index = collection.Count;
|
||||
InsertItem(index, item);
|
||||
|
||||
UpdateSelection(item);
|
||||
}
|
||||
|
||||
public void Add(object item)
|
||||
@@ -399,12 +401,17 @@ public partial class ObservableCollection<TItem> :
|
||||
{
|
||||
T? item = Factory.Create<T>(parameters);
|
||||
InsertItem(index, item);
|
||||
UpdateSelection(item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void Insert(int index, TItem item) =>
|
||||
public void Insert(int index,
|
||||
TItem item)
|
||||
{
|
||||
InsertItem(index, item);
|
||||
UpdateSelection(item);
|
||||
}
|
||||
|
||||
void IList.Insert(int index,
|
||||
object? value)
|
||||
@@ -412,6 +419,7 @@ public partial class ObservableCollection<TItem> :
|
||||
if (value is TItem item)
|
||||
{
|
||||
Insert(index, item);
|
||||
UpdateSelection(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,8 +432,27 @@ public partial class ObservableCollection<TItem> :
|
||||
|
||||
TItem item = this[oldIndex];
|
||||
|
||||
bool moveSelection = false;
|
||||
if (item is ISelectable oldSelection)
|
||||
{
|
||||
if (oldSelection.Selected)
|
||||
{
|
||||
moveSelection = true;
|
||||
SelectedItem = default;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveItem(oldIndex);
|
||||
Insert(newIndex, item);
|
||||
InsertItem(newIndex, item);
|
||||
|
||||
if (moveSelection)
|
||||
{
|
||||
if (item is ISelectable newSelection)
|
||||
{
|
||||
newSelection.Selected = true;
|
||||
dispatcher.Invoke(() => SelectedItem = item);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -535,7 +562,6 @@ public partial class ObservableCollection<TItem> :
|
||||
}
|
||||
}));
|
||||
|
||||
UpdateSelection(item);
|
||||
collection.Insert(index > Count ? Count : index, item);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ public class Publisher(IHandlerProvider handlerProvider,
|
||||
Type handlerType = typeof(NotificationHandlerWrapper<>)
|
||||
.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))
|
||||
{
|
||||
handlers.Add(handler);
|
||||
|
||||
@@ -9,11 +9,14 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
public void Add(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
object? key = GetKeyFromHandler(subscriber);
|
||||
|
||||
IDictionary<Type, object> keys = GetKeysFromHandler(subscriber);
|
||||
foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
keys.TryGetValue(argumentType, out object? key);
|
||||
|
||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}";
|
||||
subscriptions.AddOrUpdate(subscriptionKey, _ => new List<WeakReference> { new(subscriber) }, (_, collection) =>
|
||||
{
|
||||
@@ -29,11 +32,13 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
public void Remove(object subscriber)
|
||||
{
|
||||
Type handlerType = subscriber.GetType();
|
||||
object? key = GetKeyFromHandler(subscriber);
|
||||
IDictionary<Type, object> keys = GetKeysFromHandler(subscriber);
|
||||
foreach (Type interfaceType in GetHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
keys.TryGetValue(argumentType, out object? key);
|
||||
|
||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}";
|
||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
||||
{
|
||||
@@ -69,9 +74,22 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
}
|
||||
}
|
||||
|
||||
private object? GetKeyFromHandler(object handler) =>
|
||||
handler.GetAttribute<NotificationAttribute>() is NotificationAttribute attribute
|
||||
? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key : null;
|
||||
//private object? GetKeyFromHandler(object handler) =>
|
||||
// handler.GetAttribute<NotificationAttribute>() is NotificationAttribute attribute
|
||||
// ? 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) =>
|
||||
handlerType.GetInterfaces().Where(interfaceType =>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user