using Microsoft.Extensions.DependencyInjection; using System.Reflection; namespace Toolkit.Foundation; public class Publisher(ISubscriptionManager subscriptionManager, IServiceProvider provider, IDispatcher dispatcher) : IPublisher { public void Publish(object key) where TMessage : new() => Publish(new TMessage(), async args => await args(), key); public void Publish(TMessage message) where TMessage : notnull => Publish(message, async args => await args(), null); public void Publish(TMessage message, object key) where TMessage : notnull => Publish(message, async args => await args(), key); public void Publish(object message, Func, Task> marshal, object? key = null) { Type notificationType = message.GetType(); List handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>) .MakeGenericType(notificationType)).ToList(); foreach (object? handler in subscriptionManager .GetHandlers(notificationType, key!)) { handlers.Add(handler); } foreach (object? handler in handlers) { if (handler is not null) { Type? handlerType = handler.GetType(); MethodInfo? handleMethod = handlerType.GetMethod("Handle", [notificationType]); if (handleMethod is not null) { marshal(() => (Task)handleMethod.Invoke(handler, new object[] { message })!); } } } } public void Publish(object message) => Publish(message, async args => await args(), null); public void Publish() where TMessage : new() => Publish(new TMessage(), async args => await args(), null); public void PublishUI(object key) where TMessage : new() => Publish(new TMessage(), args => dispatcher.Invoke(async () => await args()), key); public void PublishUI(TMessage message) where TMessage : notnull => Publish(message, args => dispatcher.Invoke(async () => await args()), null); public void PublishUI(TMessage message, object key) where TMessage : notnull => Publish(message, args => dispatcher.Invoke(async () => await args()), key); public void PublishUI() where TMessage : new() => Publish(new TMessage(), args => dispatcher.Invoke(async () => await args()), null); public void PublishUI(object message) => Publish(message, args => dispatcher.Invoke(async () => await args()), null); }