├── LeVent ├── LeVent.png ├── LeVent_git_logo.png ├── Resources │ ├── Images │ │ ├── LeVent.psd │ │ ├── LeVent_48.png │ │ ├── LeVent_64.png │ │ ├── LeVent_128.png │ │ ├── LeVent_256.png │ │ ├── LeVent_512.png │ │ ├── LeVent_logo.psd │ │ └── LeVent_git_logo.png │ └── icons │ │ ├── levent-win.ico │ │ └── levent-mac.icns ├── Brokers │ └── Storages │ │ ├── IStorageBroker.cs │ │ ├── IStorageBroker.EventHandlerRegistrations.cs │ │ ├── StorageBroker.EventHandlerRegistrations.cs │ │ └── StorageBroker.cs ├── Models │ ├── Processings │ │ └── Events │ │ │ └── Exceptions │ │ │ ├── NullEventProcessingException.cs │ │ │ ├── NullEventHandlerProcessingException.cs │ │ │ ├── EventProcessingServiceException.cs │ │ │ ├── EventProcessingDependencyException.cs │ │ │ ├── EventProcessingValidationException.cs │ │ │ ├── EventProcessingDependencyValidationException.cs │ │ │ └── FailedEventProcessingServiceException.cs │ ├── Clients │ │ └── Exceptions │ │ │ ├── LeVentServiceException.cs │ │ │ ├── LeVentDependencyException.cs │ │ │ └── LeVentValidationException.cs │ └── Foundations │ │ └── EventHandlerRegistrations │ │ ├── EventHandlerRegistration.cs │ │ └── Exceptions │ │ ├── NullEventHandlerRegistrationException.cs │ │ ├── InvalidEventHandlerRegistrationException.cs │ │ ├── EventHandlerRegistrationServiceException.cs │ │ ├── EventHandlerRegistrationValidationException.cs │ │ └── FailedEventHandlerRegistrationServiceException.cs ├── Clients │ ├── ILeventClient.cs │ └── LeventClient.cs ├── Services │ ├── Processings │ │ └── Events │ │ │ ├── IEventProcessingService.cs │ │ │ ├── EventProcessingService.Validations.cs │ │ │ ├── EventProcessingService.cs │ │ │ └── EventProcessingService.Exceptions.cs │ └── Foundations │ │ └── EventHandlerRegistrations │ │ ├── IEventHandlerRegistrationService.cs │ │ ├── EventHandlerRegistrationService.cs │ │ ├── EventHandlerRegistrationService.Validations.cs │ │ └── EventHandlerRegistrationService.Exceptions.cs ├── license.txt └── LeVent.csproj ├── LeVent.Tests.Manual ├── LeVent.Tests.Manual.csproj ├── Brokers │ └── Events │ │ ├── IEventBroker.cs │ │ ├── EventBroker.cs │ │ ├── IEventBroker.Student.cs │ │ └── EventBroker.Students.cs ├── Models │ └── Students │ │ └── Student.cs ├── Services │ ├── Foundations │ │ ├── Students │ │ │ ├── IStudentService.cs │ │ │ └── StudentService.cs │ │ ├── StudentLibraries │ │ │ ├── IStudentLibraryService.cs │ │ │ └── StudentLibraryService.cs │ │ └── StudentEvents │ │ │ ├── IStudentEventService.cs │ │ │ └── StudentEventService.cs │ └── Orchestrations │ │ ├── StudentLibraries │ │ ├── IStudentLibraryOrchestrationService.cs │ │ └── StudentLibraryOrchestrationService.cs │ │ └── Students │ │ ├── IStudentOrchestrationService.cs │ │ └── StudentOrchestrationService.cs └── Program.cs ├── LeVent.Infrastructure.Build ├── LeVent.Infrastructure.Build.csproj ├── Program.cs └── Services │ └── ScriptGenerations │ └── ScriptGenerationService.cs ├── LeVent.Tests.Acceptance ├── LeVent.Tests.Acceptance.csproj └── LeVentClientTests.cs ├── LICENSE.txt ├── LeVent.Tests.Unit ├── LeVent.Tests.Unit.csproj └── Services │ ├── Foundations │ └── EventHandlerRegistrations │ │ ├── EventRegistrationServiceTests.Logics.Add.cs │ │ ├── EventRegistrationServiceTests.Logics.RetrieveAll.cs │ │ ├── EventRegistrationServiceTests.cs │ │ ├── EventRegistrationServiceTests.Exceptions.RetrieveAll.cs │ │ ├── EventsRegistrationServiceTests.Exceptions.Add.cs │ │ └── EventsRegistrationServiceTests.Validations.Add.cs │ └── Processings │ └── Events │ ├── EventProcessingServiceTests.Validations.Publish.cs │ ├── EventProcessingServiceTests.Validations.Add.cs │ ├── EventProcessingServiceTests.Exceptions.Publish.cs │ ├── EventProcessingServiceTests.Logic.Add.cs │ ├── EventProcessingServiceTests.cs │ ├── EventProcessingServiceTests.Logic.Publish.cs │ └── EventProcessingServiceTests.Exceptions.Add.cs ├── .gitattributes ├── LeVent.sln ├── .github └── workflows │ └── dotnet.yml ├── .gitignore └── README.md /LeVent/LeVent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/LeVent.png -------------------------------------------------------------------------------- /LeVent/LeVent_git_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/LeVent_git_logo.png -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent.psd -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_48.png -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_64.png -------------------------------------------------------------------------------- /LeVent/Resources/icons/levent-win.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/icons/levent-win.ico -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_128.png -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_256.png -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_512.png -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_logo.psd -------------------------------------------------------------------------------- /LeVent/Resources/icons/levent-mac.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/icons/levent-mac.icns -------------------------------------------------------------------------------- /LeVent/Resources/Images/LeVent_git_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/The-Standard-Organization/LeVent/HEAD/LeVent/Resources/Images/LeVent_git_logo.png -------------------------------------------------------------------------------- /LeVent/Brokers/Storages/IStorageBroker.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | namespace LeVent.Brokers.Storages 6 | { 7 | public partial interface IStorageBroker 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/LeVent.Tests.Manual.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | disable 7 | disable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LeVent.Infrastructure.Build/LeVent.Infrastructure.Build.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | disable 7 | disable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Brokers/Events/IEventBroker.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | namespace LeVent.Tests.Manual.Brokers.Events 7 | { 8 | public partial interface IEventBroker 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LeVent.Infrastructure.Build/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using LeVent.Infrastructure.Build.Services.ScriptGenerations; 6 | 7 | var scriptGenerationService = new ScriptGenerationService(); 8 | scriptGenerationService.GenerateBuildScript(); 9 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Models/Students/Student.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | 7 | namespace LeVent.Tests.Manual.Models.Students 8 | { 9 | public class Student 10 | { 11 | public Guid Id { get; set; } 12 | public string Name { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/Students/IStudentService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using LeVent.Tests.Manual.Models.Students; 6 | 7 | namespace LeVent.Tests.Manual.Services.Foundations.Students 8 | { 9 | public interface IStudentService 10 | { 11 | void AddStudent(Student student); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Orchestrations/StudentLibraries/IStudentLibraryOrchestrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | namespace LeVent.Tests.Manual.Services.Orchestrations.StudentLibraries 6 | { 7 | public interface IStudentLibraryOrchestrationService 8 | { 9 | void ListenToStudentEvents(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/StudentLibraries/IStudentLibraryService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using LeVent.Tests.Manual.Models.Students; 6 | 7 | namespace LeVent.Tests.Manual.Services.Foundations.StudentLibraries 8 | { 9 | public interface IStudentLibraryService 10 | { 11 | void RegisterStudentLibaryCard(Student student); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/NullEventProcessingException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Processings.Events.Exceptions 8 | { 9 | public class NullEventProcessingException : Xeption 10 | { 11 | public NullEventProcessingException(string message) 12 | : base(message) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Clients/Exceptions/LeVentServiceException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Clients.Exceptions 8 | { 9 | public class LeVentServiceException : Xeption 10 | { 11 | public LeVentServiceException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Clients/Exceptions/LeVentDependencyException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Clients.Exceptions 8 | { 9 | public class LeVentDependencyException : Xeption 10 | { 11 | public LeVentDependencyException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Clients/Exceptions/LeVentValidationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Clients.Exceptions 8 | { 9 | public class LeVentValidationException : Xeption 10 | { 11 | public LeVentValidationException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Clients/ILeventClient.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System; 7 | using System.Threading.Tasks; 8 | 9 | namespace LeVent.Clients 10 | { 11 | public interface ILeVentClient 12 | { 13 | void RegisterEventHandler(Func eventHandler, string eventName = null); 14 | ValueTask PublishEventAsync(T @event, string eventName = null); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Brokers/Events/EventBroker.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using LeVent.Clients; 7 | using LeVent.Tests.Manual.Models.Students; 8 | 9 | namespace LeVent.Tests.Manual.Brokers.Events 10 | { 11 | public partial class EventBroker : IEventBroker 12 | { 13 | public EventBroker() => 14 | this.StudentEventClient = new LeVentClient(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Orchestrations/Students/IStudentOrchestrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Threading.Tasks; 6 | using LeVent.Tests.Manual.Models.Students; 7 | 8 | namespace LeVent.Tests.Manual.Services.Orchestrations.Students 9 | { 10 | public interface IStudentOrchestrationService 11 | { 12 | ValueTask AddStudentAsync(Student student); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/NullEventHandlerProcessingException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Processings.Events.Exceptions 8 | { 9 | public class NullEventHandlerProcessingException : Xeption 10 | { 11 | public NullEventHandlerProcessingException(string message) 12 | : base(message) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/Students/StudentService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using LeVent.Tests.Manual.Models.Students; 7 | 8 | namespace LeVent.Tests.Manual.Services.Foundations.Students 9 | { 10 | public class StudentService : IStudentService 11 | { 12 | public void AddStudent(Student student) => 13 | Console.WriteLine($"{student.Name} Added."); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/EventProcessingServiceException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Foundations.Events.Exceptions 8 | { 9 | public class EventProcessingServiceException : Xeption 10 | { 11 | public EventProcessingServiceException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/EventHandlerRegistration.cs: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Organization, a coalition of the Good-Hearted Engineers 3 | // ---------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace LeVent.Models.Foundations.EventHandlerRegistrations 9 | { 10 | public class EventHandlerRegistration 11 | { 12 | public Func EventHandler { get; set; } 13 | public string EventName { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/EventProcessingDependencyException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Processings.Events.Exceptions 8 | { 9 | public class EventProcessingDependencyException : Xeption 10 | { 11 | public EventProcessingDependencyException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/EventProcessingValidationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Processings.Events.Exceptions 8 | { 9 | public class EventProcessingValidationException : Xeption 10 | { 11 | public EventProcessingValidationException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Services/Processings/Events/IEventProcessingService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | 8 | namespace LeVent.Services.Processings.Events 9 | { 10 | public interface IEventProcessingService 11 | { 12 | void AddEventHandler(Func eventHandler, string eventName = null); 13 | ValueTask PublishEventAsync(T @event, string eventName = null); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/Exceptions/NullEventHandlerRegistrationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions 8 | { 9 | public class NullEventHandlerRegistrationException : Xeption 10 | { 11 | public NullEventHandlerRegistrationException(string message) 12 | : base(message) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/Exceptions/InvalidEventHandlerRegistrationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions 8 | { 9 | public class InvalidEventHandlerRegistrationException : Xeption 10 | { 11 | public InvalidEventHandlerRegistrationException(string message) 12 | : base(message) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Brokers/Events/IEventBroker.Student.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System; 7 | using System.Threading.Tasks; 8 | using LeVent.Tests.Manual.Models.Students; 9 | 10 | namespace LeVent.Tests.Manual.Brokers.Events 11 | { 12 | public partial interface IEventBroker 13 | { 14 | void RegisterStudentHandler(Func studentHandler); 15 | ValueTask PublishStudentEventAsync(Student student); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/EventProcessingDependencyValidationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Processings.Events.Exceptions 8 | { 9 | public class EventProcessingDependencyValidationException : Xeption 10 | { 11 | public EventProcessingDependencyValidationException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Processings/Events/Exceptions/FailedEventProcessingServiceException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using Xeptions; 7 | 8 | namespace LeVent.Models.Foundations.Events.Exceptions 9 | { 10 | public class FailedEventProcessingServiceException : Xeption 11 | { 12 | public FailedEventProcessingServiceException(string message, Exception innerException) 13 | : base(message, innerException) 14 | { } 15 | } 16 | } -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/StudentLibraries/StudentLibraryService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using LeVent.Tests.Manual.Models.Students; 7 | 8 | namespace LeVent.Tests.Manual.Services.Foundations.StudentLibraries 9 | { 10 | public class StudentLibraryService : IStudentLibraryService 11 | { 12 | public void RegisterStudentLibaryCard(Student student) => 13 | Console.WriteLine($"{student.Name} Library Card Registered"); 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/Exceptions/EventHandlerRegistrationServiceException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using Xeptions; 7 | 8 | namespace LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions 9 | { 10 | public class EventHandlerRegistrationServiceException : Xeption 11 | { 12 | public EventHandlerRegistrationServiceException(string message, Xeption innerException) 13 | : base(message, innerException) 14 | { } 15 | } 16 | } -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/Exceptions/EventHandlerRegistrationValidationException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using Xeptions; 6 | 7 | namespace LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions 8 | { 9 | public class EventHandlerRegistrationValidationException : Xeption 10 | { 11 | public EventHandlerRegistrationValidationException(string message, Xeption innerException) 12 | : base(message, innerException) 13 | { } 14 | } 15 | } -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/StudentEvents/IStudentEventService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Tests.Manual.Models.Students; 8 | 9 | namespace LeVent.Tests.Manual.Services.Foundations.StudentEvents 10 | { 11 | public interface IStudentEventService 12 | { 13 | void RegisterStudentEventHandler(Func studentEventHandler); 14 | ValueTask PublishStudentEventAsync(Student student); 15 | } 16 | } -------------------------------------------------------------------------------- /LeVent/Brokers/Storages/IStorageBroker.EventHandlerRegistrations.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System.Collections.Generic; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | 9 | namespace LeVent.Brokers.Storages 10 | { 11 | public partial interface IStorageBroker 12 | { 13 | void InsertEventHandlerRegistration(EventHandlerRegistration eventHandlerRegistration); 14 | List> SelectAllEventHandlerRegistrations(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LeVent/Models/Foundations/EventHandlerRegistrations/Exceptions/FailedEventHandlerRegistrationServiceException.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using Xeptions; 7 | 8 | namespace LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions 9 | { 10 | public class FailedEventHandlerRegistrationServiceException : Xeption 11 | { 12 | public FailedEventHandlerRegistrationServiceException(string message, Exception innerException) 13 | : base(message, innerException) 14 | { } 15 | } 16 | } -------------------------------------------------------------------------------- /LeVent/Services/Foundations/EventHandlerRegistrations/IEventHandlerRegistrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Collections.Generic; 6 | using LeVent.Models.Foundations.EventHandlerRegistrations; 7 | 8 | namespace LeVent.Services.Foundations.EventRegistrations 9 | { 10 | public interface IEventHandlerRegistrationService 11 | { 12 | void AddEventHandlerRegistation(EventHandlerRegistration eventHandlerRegistration); 13 | List> RetrieveAllEventHandlerRegistrations(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /LeVent/Brokers/Storages/StorageBroker.EventHandlerRegistrations.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System.Collections.Generic; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | 9 | namespace LeVent.Brokers.Storages 10 | { 11 | public partial class StorageBroker 12 | { 13 | public void InsertEventHandlerRegistration(EventHandlerRegistration eventHandlerRegistration) => 14 | EventHandlerRegistrations.Add(eventHandlerRegistration); 15 | 16 | public List> SelectAllEventHandlerRegistrations() => 17 | EventHandlerRegistrations; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LeVent/Brokers/Storages/StorageBroker.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using LeVent.Models.Foundations.EventHandlerRegistrations; 10 | 11 | namespace LeVent.Brokers.Storages 12 | { 13 | public partial class StorageBroker : IStorageBroker 14 | { 15 | private static List> EventHandlers; 16 | private static List> EventHandlerRegistrations; 17 | 18 | public StorageBroker() 19 | { 20 | EventHandlers = new List>(); 21 | EventHandlerRegistrations = new List>(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Brokers/Events/EventBroker.Students.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System; 7 | using System.Threading.Tasks; 8 | using LeVent.Clients; 9 | using LeVent.Tests.Manual.Models.Students; 10 | 11 | namespace LeVent.Tests.Manual.Brokers.Events 12 | { 13 | public partial class EventBroker 14 | { 15 | public ILeVentClient StudentEventClient { get; set; } 16 | 17 | public async ValueTask PublishStudentEventAsync(Student student) => 18 | await this.StudentEventClient.PublishEventAsync(student); 19 | 20 | public void RegisterStudentHandler(Func studentHandler) => 21 | this.StudentEventClient.RegisterEventHandler(studentHandler); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LeVent.Tests.Acceptance/LeVent.Tests.Acceptance.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | disable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Foundations/StudentEvents/StudentEventService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Tests.Manual.Brokers.Events; 8 | using LeVent.Tests.Manual.Models.Students; 9 | 10 | namespace LeVent.Tests.Manual.Services.Foundations.StudentEvents 11 | { 12 | public class StudentEventService : IStudentEventService 13 | { 14 | private readonly IEventBroker eventBroker; 15 | 16 | public StudentEventService(IEventBroker eventBroker) => 17 | this.eventBroker = eventBroker; 18 | 19 | public async ValueTask PublishStudentEventAsync(Student student) => 20 | await this.eventBroker.PublishStudentEventAsync(student); 21 | 22 | public void RegisterStudentEventHandler(Func studentEventHandler) => 23 | this.eventBroker.RegisterStudentHandler(studentEventHandler); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LeVent/Services/Processings/Events/EventProcessingService.Validations.cs: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ---------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Models.Processings.Events.Exceptions; 8 | 9 | namespace LeVent.Services.Processings.Events 10 | { 11 | public partial class EventProcessingService : IEventProcessingService 12 | { 13 | private static void ValidateEventHandler(Func eventHandler) 14 | { 15 | if (eventHandler is null) 16 | { 17 | throw new NullEventHandlerProcessingException( 18 | message: "Event handler is null"); 19 | } 20 | } 21 | 22 | private static void ValidateEvent(T @event) 23 | { 24 | if (@event == null) 25 | { 26 | throw new NullEventProcessingException( 27 | message: "Event is null"); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/LeVent.Tests.Unit.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | disable 6 | disable 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | all 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Orchestrations/Students/StudentOrchestrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Threading.Tasks; 6 | using LeVent.Tests.Manual.Models.Students; 7 | using LeVent.Tests.Manual.Services.Foundations.StudentEvents; 8 | using LeVent.Tests.Manual.Services.Foundations.Students; 9 | 10 | namespace LeVent.Tests.Manual.Services.Orchestrations.Students 11 | { 12 | public class StudentOrchestrationService : IStudentOrchestrationService 13 | { 14 | private readonly IStudentEventService studentEventService; 15 | private readonly IStudentService studentService; 16 | 17 | public StudentOrchestrationService( 18 | IStudentEventService studentEventService, 19 | IStudentService studentService) 20 | { 21 | this.studentEventService = studentEventService; 22 | this.studentService = studentService; 23 | } 24 | 25 | public async ValueTask AddStudentAsync(Student student) 26 | { 27 | this.studentService.AddStudent(student); 28 | await this.studentEventService.PublishStudentEventAsync(student); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LeVent/Services/Foundations/EventHandlerRegistrations/EventHandlerRegistrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Collections.Generic; 6 | using LeVent.Brokers.Storages; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | 9 | namespace LeVent.Services.Foundations.EventRegistrations 10 | { 11 | public partial class EventHandlerRegistrationService : IEventHandlerRegistrationService 12 | { 13 | private readonly IStorageBroker storageBroker; 14 | 15 | public EventHandlerRegistrationService(IStorageBroker storageBroker) => 16 | this.storageBroker = storageBroker; 17 | 18 | public void AddEventHandlerRegistation(EventHandlerRegistration eventHandlerRegistration) => 19 | TryCatch(() => 20 | { 21 | ValidateEventHandlerRegistration(eventHandlerRegistration); 22 | 23 | this.storageBroker.InsertEventHandlerRegistration(eventHandlerRegistration); 24 | }); 25 | 26 | public List> RetrieveAllEventHandlerRegistrations() => 27 | TryCatch(() => this.storageBroker.SelectAllEventHandlerRegistrations()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventRegistrationServiceTests.Logics.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using LeVent.Models.Foundations.EventHandlerRegistrations; 6 | using Moq; 7 | using Xunit; 8 | 9 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 10 | { 11 | public partial class EventHandlerRegistrationServiceTests 12 | { 13 | [Fact] 14 | private void ShouldAddEventHandlerRegistration() 15 | { 16 | // given 17 | EventHandlerRegistration randomEventHandlerRegistration = 18 | CreateRandomEventHandlerRegistration(); 19 | 20 | EventHandlerRegistration inputEventHandlerRegistration = 21 | randomEventHandlerRegistration; 22 | 23 | // when 24 | this.eventHandlerRegistrationService.AddEventHandlerRegistation( 25 | inputEventHandlerRegistration); 26 | 27 | // then 28 | this.storageBrokerMock.Verify(broker => 29 | broker.InsertEventHandlerRegistration( 30 | inputEventHandlerRegistration), 31 | Times.Once); 32 | 33 | this.storageBrokerMock.VerifyNoOtherCalls(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Services/Orchestrations/StudentLibraries/StudentLibraryOrchestrationService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Threading.Tasks; 6 | using LeVent.Tests.Manual.Services.Foundations.StudentEvents; 7 | using LeVent.Tests.Manual.Services.Foundations.StudentLibraries; 8 | 9 | namespace LeVent.Tests.Manual.Services.Orchestrations.StudentLibraries 10 | { 11 | public class StudentLibraryOrchestrationService : IStudentLibraryOrchestrationService 12 | { 13 | private readonly IStudentEventService studentEventService; 14 | private readonly IStudentLibraryService studentLibraryService; 15 | 16 | public StudentLibraryOrchestrationService( 17 | IStudentEventService studentEventService, 18 | IStudentLibraryService studentLibraryService) 19 | { 20 | this.studentEventService = studentEventService; 21 | this.studentLibraryService = studentLibraryService; 22 | } 23 | 24 | public void ListenToStudentEvents() 25 | { 26 | this.studentEventService.RegisterStudentEventHandler((student) => 27 | { 28 | this.studentLibraryService.RegisterStudentLibaryCard(student); 29 | 30 | return ValueTask.CompletedTask; 31 | }); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LeVent/license.txt: -------------------------------------------------------------------------------- 1 | LeVent - .NET Core Library 2 | 3 | Copyright (c) 2022 Hassan Habib All rights reserved. 4 | 5 | Material in this repository is made available under the following terms: 6 | 1. Code is licensed under the MIT license, reproduced below. 7 | 2. Documentation is licensed under the Creative Commons Attribution 3.0 United States (Unported) License. 8 | The text of the license can be found here: http://creativecommons.org/licenses/by/3.0/legalcode 9 | 10 | The MIT License (MIT) 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or substantial 19 | portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES 24 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LeVent/LeVent.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | disable 6 | LeVent 7 | Hassan Habib | Kailu Hu 8 | PiorSoft, LLC 9 | Local Eventing .NET Library 10 | Copyright (c) Hassan Habib 11 | true 12 | true 13 | LeVent.png 14 | 15 | 1.2 16 | 1.2.0.0 17 | 1.2.0.0 18 | en-US 19 | 20 | https://github.com/hassanhabib/LeVent 21 | license.txt 22 | https://github.com/hassanhabib/LeVent 23 | Github 24 | Events .NET 25 | Added Basic Events with Target Event Name 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Always 36 | True 37 | \ 38 | 39 | 40 | Always 41 | True 42 | \ 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /LeVent.Tests.Manual/Program.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Tests.Manual.Brokers.Events; 8 | using LeVent.Tests.Manual.Models.Students; 9 | using LeVent.Tests.Manual.Services.Foundations.StudentEvents; 10 | using LeVent.Tests.Manual.Services.Foundations.StudentLibraries; 11 | using LeVent.Tests.Manual.Services.Foundations.Students; 12 | using LeVent.Tests.Manual.Services.Orchestrations.StudentLibraries; 13 | using LeVent.Tests.Manual.Services.Orchestrations.Students; 14 | 15 | namespace LeVent.Tests.Manual 16 | { 17 | internal class Program 18 | { 19 | static async Task Main(string[] args) 20 | { 21 | var someStudent = new Student 22 | { 23 | Id = Guid.NewGuid(), 24 | Name = "Kailu Hu" 25 | }; 26 | 27 | var eventBroker = new EventBroker(); 28 | var studentService = new StudentService(); 29 | var studentLibraryService = new StudentLibraryService(); 30 | var studentEventService = new StudentEventService(eventBroker); 31 | 32 | var studentLibraryOrchestrationService = 33 | new StudentLibraryOrchestrationService( 34 | studentEventService, 35 | studentLibraryService); 36 | 37 | var studentOrchestrationService = 38 | new StudentOrchestrationService( 39 | studentEventService, 40 | studentService); 41 | 42 | studentLibraryOrchestrationService.ListenToStudentEvents(); 43 | await studentOrchestrationService.AddStudentAsync(someStudent); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventRegistrationServiceTests.Logics.RetrieveAll.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Collections.Generic; 6 | using FluentAssertions; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using Moq; 9 | using Xunit; 10 | 11 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 12 | { 13 | public partial class EventHandlerRegistrationServiceTests 14 | { 15 | [Fact] 16 | private void ShouldRetrieveAllEventHandlerRegistrations() 17 | { 18 | // given 19 | List> randomEventHandlerRegistrations = 20 | CreateRandomEventHandlerRegistrations(); 21 | 22 | List> storageEventHandlerRegistrations = 23 | randomEventHandlerRegistrations; 24 | 25 | List> expectedEventHandlerRegistrations = 26 | storageEventHandlerRegistrations; 27 | 28 | this.storageBrokerMock.Setup(broker => 29 | broker.SelectAllEventHandlerRegistrations()) 30 | .Returns(storageEventHandlerRegistrations); 31 | 32 | // when 33 | List> actualEventHandlerRegistrations = 34 | this.eventHandlerRegistrationService.RetrieveAllEventHandlerRegistrations(); 35 | 36 | // then 37 | actualEventHandlerRegistrations.Should().BeEquivalentTo( 38 | expectedEventHandlerRegistrations); 39 | 40 | this.storageBrokerMock.Verify(broker => 41 | broker.SelectAllEventHandlerRegistrations(), 42 | Times.Once); 43 | 44 | this.storageBrokerMock.VerifyNoOtherCalls(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Validations.Publish.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Threading.Tasks; 6 | using FluentAssertions; 7 | using LeVent.Models.Processings.Events.Exceptions; 8 | using Moq; 9 | using Xunit; 10 | 11 | namespace LeVent.Tests.Unit.Services.Foundations.Events 12 | { 13 | public partial class EventProcessingServiceTests 14 | { 15 | [Fact] 16 | private async Task ShouldThrowValidationExceptionOnAddIfEventIsNullAsync() 17 | { 18 | // given 19 | object nullEvent = null; 20 | 21 | var nullEventProcessingException = 22 | new NullEventProcessingException( 23 | message: "Event is null"); 24 | 25 | var expectedEventProcessingValidationException = 26 | new EventProcessingValidationException( 27 | message: "Event validation error occurred, please fix error and try again.", 28 | innerException: nullEventProcessingException); 29 | 30 | // when 31 | ValueTask publishEventTask = this.eventProcessingService 32 | .PublishEventAsync(nullEvent); 33 | 34 | EventProcessingValidationException actualEventProcessingValidationException = 35 | await Assert.ThrowsAsync( 36 | publishEventTask.AsTask); 37 | 38 | // then 39 | actualEventProcessingValidationException.Should() 40 | .BeEquivalentTo(expectedEventProcessingValidationException); 41 | 42 | this.eventHandlerRegistrationServiceMock.Verify(broker => 43 | broker.RetrieveAllEventHandlerRegistrations(), 44 | Times.Never); 45 | 46 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Validations.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using FluentAssertions; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations; 9 | using LeVent.Models.Processings.Events.Exceptions; 10 | using Moq; 11 | using Xunit; 12 | 13 | namespace LeVent.Tests.Unit.Services.Foundations.Events 14 | { 15 | public partial class EventProcessingServiceTests 16 | { 17 | [Fact] 18 | private void ShouldThrowValidationExceptionOnAddIfEventHandlerIsNull() 19 | { 20 | // given 21 | Func nullEventHandler = null; 22 | 23 | var nullEventHandlerProcessingException = 24 | new NullEventHandlerProcessingException( 25 | message: "Event handler is null"); 26 | 27 | var expectedEventProcessingValidationException = 28 | new EventProcessingValidationException( 29 | message: "Event validation error occurred, please fix error and try again.", 30 | innerException: nullEventHandlerProcessingException); 31 | 32 | // when 33 | Action addEventHandlerAction = () => 34 | this.eventProcessingService.AddEventHandler(nullEventHandler); 35 | 36 | EventProcessingValidationException actualEventProcessingValidationException = 37 | Assert.Throws(addEventHandlerAction); 38 | 39 | // then 40 | actualEventProcessingValidationException.Should() 41 | .BeEquivalentTo(expectedEventProcessingValidationException); 42 | 43 | this.eventHandlerRegistrationServiceMock.Verify(service => 44 | service.AddEventHandlerRegistation( 45 | It.IsAny>()), 46 | Times.Never); 47 | 48 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventRegistrationServiceTests.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using LeVent.Brokers.Storages; 10 | using LeVent.Models.Foundations.EventHandlerRegistrations; 11 | using LeVent.Services.Foundations.EventRegistrations; 12 | using Moq; 13 | using Tynamix.ObjectFiller; 14 | 15 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 16 | { 17 | public partial class EventHandlerRegistrationServiceTests 18 | { 19 | private readonly Mock> storageBrokerMock; 20 | private readonly IEventHandlerRegistrationService eventHandlerRegistrationService; 21 | 22 | public EventHandlerRegistrationServiceTests() 23 | { 24 | this.storageBrokerMock = new Mock>(); 25 | 26 | this.eventHandlerRegistrationService = new EventHandlerRegistrationService( 27 | storageBroker: this.storageBrokerMock.Object); 28 | } 29 | 30 | private static List> CreateRandomEventHandlerRegistrations() => 31 | CreateEventHandlerRegistrationFiller().Create(count: GetRandomNumber()).ToList(); 32 | 33 | private static EventHandlerRegistration CreateRandomEventHandlerRegistration() => 34 | CreateEventHandlerRegistrationFiller().Create(); 35 | 36 | private static int GetRandomNumber() => 37 | new IntRange(min: 2, max: 10).GetValue(); 38 | 39 | private static Filler> CreateEventHandlerRegistrationFiller() 40 | { 41 | var filler = new Filler>(); 42 | 43 | filler.Setup() 44 | .OnProperty(registrationHandler => registrationHandler.EventHandler) 45 | .Use(new Mock>().Object); 46 | 47 | return filler; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /LeVent/Services/Processings/Events/EventProcessingService.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using LeVent.Models.Foundations.EventHandlerRegistrations; 10 | using LeVent.Services.Foundations.EventRegistrations; 11 | 12 | namespace LeVent.Services.Processings.Events 13 | { 14 | public partial class EventProcessingService : IEventProcessingService 15 | { 16 | private readonly IEventHandlerRegistrationService eventHandlerRegistrationService; 17 | 18 | public EventProcessingService(IEventHandlerRegistrationService eventHandlerRegistrationService) => 19 | this.eventHandlerRegistrationService = eventHandlerRegistrationService; 20 | 21 | public void AddEventHandler(Func eventHandler, string eventName = null) => 22 | TryCatch(() => 23 | { 24 | ValidateEventHandler(eventHandler); 25 | 26 | var eventHandlerRegistration = new EventHandlerRegistration 27 | { 28 | EventHandler = eventHandler, 29 | EventName = eventName 30 | }; 31 | 32 | this.eventHandlerRegistrationService.AddEventHandlerRegistation( 33 | eventHandlerRegistration); 34 | }); 35 | 36 | public ValueTask PublishEventAsync(T @event, string eventName = null) => 37 | TryCatch(async () => 38 | { 39 | ValidateEvent(@event); 40 | 41 | List> registrations = 42 | this.eventHandlerRegistrationService 43 | .RetrieveAllEventHandlerRegistrations(); 44 | 45 | List> eventHandlers = 46 | registrations.Where(registration => 47 | registration.EventName == eventName) 48 | .Select(registration => 49 | registration.EventHandler) 50 | .ToList(); 51 | 52 | foreach (Func eventHandler in eventHandlers) 53 | { 54 | await eventHandler(@event); 55 | } 56 | }); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Exceptions.Publish.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using FluentAssertions; 8 | using LeVent.Models.Foundations.Events.Exceptions; 9 | using Moq; 10 | using Xunit; 11 | 12 | namespace LeVent.Tests.Unit.Services.Foundations.Events 13 | { 14 | public partial class EventProcessingServiceTests 15 | { 16 | [Fact] 17 | private async Task ShouldThrowServiceExceptionOnPublishIfServiceErrorOccursAsync() 18 | { 19 | // given 20 | var someEvent = new object(); 21 | var serviceException = new Exception(); 22 | 23 | var failedEventProcessingServiceException = 24 | new FailedEventProcessingServiceException( 25 | message: "Failed event service error ocurred, contact support.", 26 | innerException: serviceException); 27 | 28 | var expectedEventServiceException = 29 | new EventProcessingServiceException( 30 | message: "Event service error occurred, contact support.", 31 | innerException: failedEventProcessingServiceException); 32 | 33 | this.eventHandlerRegistrationServiceMock.Setup(service => 34 | service.RetrieveAllEventHandlerRegistrations()) 35 | .Throws(serviceException); 36 | 37 | // when 38 | ValueTask publishEventTask = this.eventProcessingService 39 | .PublishEventAsync(someEvent); 40 | 41 | EventProcessingServiceException actualEventProcessingServiceException = 42 | await Assert.ThrowsAsync( 43 | publishEventTask.AsTask); 44 | 45 | // then 46 | actualEventProcessingServiceException.Should() 47 | .BeEquivalentTo(expectedEventServiceException); 48 | 49 | this.eventHandlerRegistrationServiceMock.Verify(service => 50 | service.RetrieveAllEventHandlerRegistrations(), 51 | Times.Once); 52 | 53 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /LeVent/Services/Foundations/EventHandlerRegistrations/EventHandlerRegistrationService.Validations.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 9 | 10 | namespace LeVent.Services.Foundations.EventRegistrations 11 | { 12 | public partial class EventHandlerRegistrationService 13 | { 14 | private static void ValidateEventHandlerRegistration( 15 | EventHandlerRegistration eventHandlerRegistration) 16 | { 17 | ValidateEventHandlerRegistrationIsNotNull(eventHandlerRegistration); 18 | 19 | Validate( 20 | (Rule: IsInvalid(eventHandlerRegistration.EventHandler), 21 | Parameter: nameof(EventHandlerRegistration.EventHandler))); 22 | } 23 | 24 | private static void ValidateEventHandlerRegistrationIsNotNull( 25 | EventHandlerRegistration eventHandlerRegistration) 26 | { 27 | if (eventHandlerRegistration is null) 28 | { 29 | throw new NullEventHandlerRegistrationException( 30 | message: "Event handler is null"); 31 | } 32 | } 33 | 34 | private static dynamic IsInvalid(Func EventHandler) => new 35 | { 36 | Condition = EventHandler == null, 37 | Message = "Handler is required" 38 | }; 39 | 40 | private static void Validate(params (dynamic Rule, string Parameter)[] validations) 41 | { 42 | var invalidEventHandlerRegistrationException = 43 | new InvalidEventHandlerRegistrationException( 44 | message: "Invalid event handler registration error ocurred, fix errors and try again."); 45 | 46 | foreach ((dynamic rule, string parameter) in validations) 47 | { 48 | if (rule.Condition) 49 | { 50 | invalidEventHandlerRegistrationException.UpsertDataList( 51 | key: parameter, 52 | value: rule.Message); 53 | } 54 | } 55 | 56 | invalidEventHandlerRegistrationException.ThrowIfContainsErrors(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventRegistrationServiceTests.Exceptions.RetrieveAll.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using FluentAssertions; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 8 | using Moq; 9 | using Xunit; 10 | 11 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 12 | { 13 | public partial class EventHandlerRegistrationServiceTests 14 | { 15 | [Fact] 16 | private void ShouldThrowServiceExceptionOnRetrieveAllIfServiceErrorOcurrs() 17 | { 18 | // given 19 | var serviceException = new Exception(); 20 | 21 | var failedEventHandlerRegistrationServiceException = 22 | new FailedEventHandlerRegistrationServiceException( 23 | message: "Failed event handler registration service error occurred, contact support.", 24 | innerException: serviceException); 25 | 26 | var expectedEventHandlerRegistrationServiceException = 27 | new EventHandlerRegistrationServiceException( 28 | message: "Event service error occurred, contact support.", 29 | innerException: failedEventHandlerRegistrationServiceException); 30 | 31 | this.storageBrokerMock.Setup(broker => 32 | broker.SelectAllEventHandlerRegistrations()) 33 | .Throws(serviceException); 34 | 35 | // when 36 | Action retrieveAllEventHandlerRegistrationsAction = () => 37 | this.eventHandlerRegistrationService 38 | .RetrieveAllEventHandlerRegistrations(); 39 | 40 | EventHandlerRegistrationServiceException 41 | actualEventHandlerRegistrationServiceException = 42 | Assert.Throws( 43 | retrieveAllEventHandlerRegistrationsAction); 44 | 45 | // then 46 | actualEventHandlerRegistrationServiceException.Should() 47 | .BeEquivalentTo(expectedEventHandlerRegistrationServiceException); 48 | 49 | this.storageBrokerMock.Verify(broker => 50 | broker.SelectAllEventHandlerRegistrations(), 51 | Times.Once); 52 | 53 | this.storageBrokerMock.VerifyNoOtherCalls(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventsRegistrationServiceTests.Exceptions.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using FluentAssertions; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 9 | using Moq; 10 | using Xunit; 11 | 12 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 13 | { 14 | public partial class EventHandlerRegistrationServiceTests 15 | { 16 | [Fact] 17 | private void ShouldThrowServiceExceptionOnAddIfServiceErrorOcurrs() 18 | { 19 | // given 20 | EventHandlerRegistration someEventHandlerRegistration = 21 | CreateRandomEventHandlerRegistration(); 22 | 23 | var serviceException = new Exception(); 24 | 25 | var failedEventHandlerRegistrationServiceException = 26 | new FailedEventHandlerRegistrationServiceException( 27 | message: "Failed event handler registration service error occurred, contact support.", 28 | innerException: serviceException); 29 | 30 | var expectedEventHandlerRegistrationServiceException = 31 | new EventHandlerRegistrationServiceException( 32 | message: "Event service error occurred, contact support.", 33 | innerException: failedEventHandlerRegistrationServiceException); 34 | 35 | this.storageBrokerMock.Setup(broker => 36 | broker.InsertEventHandlerRegistration( 37 | It.IsAny>())) 38 | .Throws(serviceException); 39 | 40 | // when 41 | Action addEventHandlerAction = () => 42 | this.eventHandlerRegistrationService.AddEventHandlerRegistation( 43 | someEventHandlerRegistration); 44 | 45 | EventHandlerRegistrationServiceException actualEventHandlerRegistrationServiceException = 46 | Assert.Throws(addEventHandlerAction); 47 | 48 | // then 49 | actualEventHandlerRegistrationServiceException.Should() 50 | .BeEquivalentTo(expectedEventHandlerRegistrationServiceException); 51 | 52 | this.storageBrokerMock.Verify(broker => 53 | broker.InsertEventHandlerRegistration( 54 | It.IsAny>()), 55 | Times.Once); 56 | 57 | this.storageBrokerMock.VerifyNoOtherCalls(); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /LeVent.Tests.Acceptance/LeVentClientTests.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | using FluentAssertions; 8 | using LeVent.Clients; 9 | using Xunit; 10 | 11 | namespace LeVent.Tests.Acceptance 12 | { 13 | public class LeVentClientTests 14 | { 15 | private static List eventResults = 16 | new List(); 17 | 18 | [Fact] 19 | public async Task ShouldRegisterPublishEventsAsync() 20 | { 21 | // given 22 | string myEvent = "nothing"; 23 | var leVentClient = new LeVentClient(); 24 | 25 | // when 26 | leVentClient.RegisterEventHandler(DoSomethingWithEvent); 27 | leVentClient.RegisterEventHandler(DoSomethingElseWithEventAsync); 28 | await leVentClient.PublishEventAsync(myEvent); 29 | 30 | // then 31 | eventResults.Count.Should().Be(2); 32 | eventResults.Should().Contain($"{myEvent} arrived @ First Handler"); 33 | eventResults.Should().Contain($"{myEvent} arrived @ Second Handler"); 34 | eventResults = new List(); 35 | } 36 | 37 | [Fact] 38 | private async Task ShouldRegisterPublishForSpecificEventNameAsync() 39 | { 40 | // given 41 | string eventName = "event name"; 42 | string myEvent = "nothing"; 43 | var leVentClient = new LeVentClient(); 44 | 45 | // when 46 | leVentClient.RegisterEventHandler( 47 | eventHandler: DoSomethingWithEvent, 48 | eventName); 49 | 50 | leVentClient.RegisterEventHandler( 51 | eventHandler: DoSomethingElseWithEventAsync, 52 | eventName); 53 | 54 | await leVentClient.PublishEventAsync(myEvent, eventName); 55 | 56 | // then 57 | eventResults.Count.Should().Be(2); 58 | eventResults.Should().Contain($"{myEvent} arrived @ First Handler"); 59 | eventResults.Should().Contain($"{myEvent} arrived @ Second Handler"); 60 | eventResults = new List(); 61 | } 62 | 63 | private ValueTask DoSomethingWithEvent(string @event) 64 | { 65 | eventResults.Add($"{@event} arrived @ First Handler"); 66 | 67 | return ValueTask.CompletedTask; 68 | } 69 | 70 | private ValueTask DoSomethingElseWithEventAsync(string @event) 71 | { 72 | eventResults.Add($"{@event} arrived @ Second Handler"); 73 | 74 | return ValueTask.CompletedTask; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Logic.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using Moq; 9 | using Xunit; 10 | 11 | namespace LeVent.Tests.Unit.Services.Foundations.Events 12 | { 13 | public partial class EventProcessingServiceTests 14 | { 15 | [Fact] 16 | private void ShouldRegisterEventHandlerWithoutEventName() 17 | { 18 | // given 19 | var eventHandlerMock = 20 | new Mock>(); 21 | 22 | Func inputEventHandler = 23 | eventHandlerMock.Object; 24 | 25 | var expectedInputEventHandlerRegistration = 26 | new EventHandlerRegistration 27 | { 28 | EventHandler = inputEventHandler, 29 | EventName = null 30 | }; 31 | 32 | // when 33 | this.eventProcessingService.AddEventHandler(inputEventHandler); 34 | 35 | // then 36 | this.eventHandlerRegistrationServiceMock.Verify(service => 37 | service.AddEventHandlerRegistation( 38 | It.Is(SameEventHandlerRegistrationAs( 39 | expectedInputEventHandlerRegistration))), 40 | Times.Once); 41 | 42 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 43 | } 44 | 45 | [Fact] 46 | private void ShouldRegisterEventHandlerWithEventName() 47 | { 48 | // given 49 | var eventHandlerMock = 50 | new Mock>(); 51 | 52 | Func inputEventHandler = 53 | eventHandlerMock.Object; 54 | 55 | string randomEventName = GetRandomEventName(); 56 | string inputEventName = randomEventName; 57 | 58 | var expectedInputEventHandlerRegistration = 59 | new EventHandlerRegistration 60 | { 61 | EventHandler = inputEventHandler, 62 | EventName = inputEventName 63 | }; 64 | 65 | // when 66 | this.eventProcessingService.AddEventHandler( 67 | inputEventHandler, 68 | inputEventName); 69 | 70 | // then 71 | this.eventHandlerRegistrationServiceMock.Verify(service => 72 | service.AddEventHandlerRegistation( 73 | It.Is(SameEventHandlerRegistrationAs( 74 | expectedInputEventHandlerRegistration))), 75 | Times.Once); 76 | 77 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /LeVent.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32819.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LeVent", "LeVent\LeVent.csproj", "{9C076A74-2175-4B66-9F6F-D4D80DE44C04}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LeVent.Tests.Unit", "LeVent.Tests.Unit\LeVent.Tests.Unit.csproj", "{E216BF0A-9A28-4589-8320-A0E77CBA83B8}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LeVent.Tests.Acceptance", "LeVent.Tests.Acceptance\LeVent.Tests.Acceptance.csproj", "{901FA460-4D76-468D-A08D-BA2C31019B20}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LeVent.Infrastructure.Build", "LeVent.Infrastructure.Build\LeVent.Infrastructure.Build.csproj", "{784AAEBF-3AAD-4288-A5E6-8541C3E49BF7}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LeVent.Tests.Manual", "LeVent.Tests.Manual\LeVent.Tests.Manual.csproj", "{34A836CA-49B6-4F1A-83AB-152931169BC6}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {9C076A74-2175-4B66-9F6F-D4D80DE44C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {9C076A74-2175-4B66-9F6F-D4D80DE44C04}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {9C076A74-2175-4B66-9F6F-D4D80DE44C04}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {9C076A74-2175-4B66-9F6F-D4D80DE44C04}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {E216BF0A-9A28-4589-8320-A0E77CBA83B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {E216BF0A-9A28-4589-8320-A0E77CBA83B8}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {E216BF0A-9A28-4589-8320-A0E77CBA83B8}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {E216BF0A-9A28-4589-8320-A0E77CBA83B8}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {901FA460-4D76-468D-A08D-BA2C31019B20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {901FA460-4D76-468D-A08D-BA2C31019B20}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {901FA460-4D76-468D-A08D-BA2C31019B20}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {901FA460-4D76-468D-A08D-BA2C31019B20}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {784AAEBF-3AAD-4288-A5E6-8541C3E49BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {784AAEBF-3AAD-4288-A5E6-8541C3E49BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {784AAEBF-3AAD-4288-A5E6-8541C3E49BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {784AAEBF-3AAD-4288-A5E6-8541C3E49BF7}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {34A836CA-49B6-4F1A-83AB-152931169BC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {34A836CA-49B6-4F1A-83AB-152931169BC6}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {34A836CA-49B6-4F1A-83AB-152931169BC6}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {34A836CA-49B6-4F1A-83AB-152931169BC6}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {638A24F5-6A2A-4A87-8E1D-9307016B6032} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /LeVent/Services/Foundations/EventHandlerRegistrations/EventHandlerRegistrationService.Exceptions.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 9 | using Xeptions; 10 | 11 | namespace LeVent.Services.Foundations.EventRegistrations 12 | { 13 | public partial class EventHandlerRegistrationService : IEventHandlerRegistrationService 14 | { 15 | private delegate void ReturningNothingFunction(); 16 | private delegate List> ReturningEventHandlerRegistrationFunction(); 17 | 18 | private void TryCatch(ReturningNothingFunction returningNothingFunction) 19 | { 20 | try 21 | { 22 | returningNothingFunction(); 23 | } 24 | catch (NullEventHandlerRegistrationException nullEventHandlerRegistrationException) 25 | { 26 | throw CreateEventHandlerRegistrationValidationException( 27 | nullEventHandlerRegistrationException); 28 | } 29 | catch (InvalidEventHandlerRegistrationException invalidEventHandlerRegistrationException) 30 | { 31 | throw CreateEventHandlerRegistrationValidationException( 32 | invalidEventHandlerRegistrationException); 33 | } 34 | catch (Exception exception) 35 | { 36 | var failedEventHandlerRegistrationServiceException = 37 | new FailedEventHandlerRegistrationServiceException( 38 | message: "Failed event handler registration service error occurred, contact support.", 39 | innerException: exception); 40 | 41 | throw CreateEventHandlerRegistrationServiceException( 42 | failedEventHandlerRegistrationServiceException); 43 | } 44 | } 45 | 46 | private List> TryCatch( 47 | ReturningEventHandlerRegistrationFunction returningEventHandlerRegistrationFunction) 48 | { 49 | try 50 | { 51 | return returningEventHandlerRegistrationFunction(); 52 | } 53 | catch (Exception exception) 54 | { 55 | var failedEventHandlerRegistrationServiceException = 56 | new FailedEventHandlerRegistrationServiceException( 57 | message: "Failed event handler registration service error occurred, contact support.", 58 | innerException: exception); 59 | 60 | throw CreateEventHandlerRegistrationServiceException( 61 | failedEventHandlerRegistrationServiceException); 62 | } 63 | } 64 | 65 | private static EventHandlerRegistrationValidationException CreateEventHandlerRegistrationValidationException( 66 | Xeption innerException) 67 | { 68 | return new EventHandlerRegistrationValidationException( 69 | message: "Event validation error occurred, please fix error and try again.", 70 | innerException: innerException); 71 | } 72 | 73 | private static EventHandlerRegistrationServiceException CreateEventHandlerRegistrationServiceException( 74 | Xeption innerException) 75 | { 76 | return new EventHandlerRegistrationServiceException( 77 | message: "Event service error occurred, contact support.", 78 | innerException: innerException); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /.github/workflows/dotnet.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out 14 | uses: actions/checkout@v3 15 | - name: Setup .Net 16 | uses: actions/setup-dotnet@v3 17 | with: 18 | dotnet-version: 7.0.201 19 | - name: Restore 20 | run: dotnet restore 21 | - name: Build 22 | run: dotnet build --no-restore 23 | - name: Test 24 | run: dotnet test --no-build --verbosity normal 25 | add_tag: 26 | runs-on: ubuntu-latest 27 | needs: 28 | - build 29 | if: >- 30 | needs.build.result == 'success' && 31 | 32 | github.event.pull_request.merged && 33 | 34 | github.event.pull_request.base.ref == 'main' && 35 | 36 | startsWith(github.event.pull_request.title, 'RELEASES:') && 37 | 38 | contains(github.event.pull_request.labels.*.name, 'RELEASES') 39 | steps: 40 | - name: Checkout code 41 | uses: actions/checkout@v3 42 | with: 43 | token: ${{ secrets.PAT_FOR_TAGGING }} 44 | - name: Configure Git 45 | run: >- 46 | git config user.name "GitHub Action" 47 | 48 | git config user.email "action@github.com" 49 | - name: Extract Version 50 | id: extract_version 51 | run: > 52 | # Running on Linux/Unix 53 | 54 | sudo apt-get install xmlstarlet 55 | 56 | version_number=$(xmlstarlet sel -t -v "//Version" -n ADotNet/ADotNet.csproj) 57 | 58 | echo "$version_number" 59 | 60 | echo "version_number<> $GITHUB_OUTPUT 61 | 62 | echo "$version_number" >> $GITHUB_OUTPUT 63 | 64 | echo "EOF" >> $GITHUB_OUTPUT 65 | shell: bash 66 | - name: Display Version 67 | run: 'echo "Version number: ${{ steps.extract_version.outputs.version_number }}"' 68 | - name: Extract Package Release Notes 69 | id: extract_package_release_notes 70 | run: > 71 | # Running on Linux/Unix 72 | 73 | sudo apt-get install xmlstarlet 74 | 75 | package_release_notes=$(xmlstarlet sel -t -v "//PackageReleaseNotes" -n ADotNet/ADotNet.csproj) 76 | 77 | echo "$package_release_notes" 78 | 79 | echo "package_release_notes<> $GITHUB_OUTPUT 80 | 81 | echo "$package_release_notes" >> $GITHUB_OUTPUT 82 | 83 | echo "EOF" >> $GITHUB_OUTPUT 84 | shell: bash 85 | - name: Display Package Release Notes 86 | run: 'echo "Package Release Notes: ${{ steps.extract_package_release_notes.outputs.package_release_notes }}"' 87 | - name: Create GitHub Tag 88 | run: >- 89 | git tag -a "v${{ steps.extract_version.outputs.version_number }}" -m "Release - v${{ steps.extract_version.outputs.version_number }}" 90 | 91 | git push origin --tags 92 | - name: Create GitHub Release 93 | uses: actions/create-release@v1 94 | with: 95 | tag_name: v${{ steps.extract_version.outputs.version_number }} 96 | release_name: Release - v${{ steps.extract_version.outputs.version_number }} 97 | body: >- 98 | ## Release - v${{ steps.extract_version.outputs.version_number }} 99 | 100 | 101 | ### Release Notes 102 | 103 | ${{ steps.extract_package_release_notes.outputs.package_release_notes }} 104 | env: 105 | GITHUB_TOKEN: ${{ secrets.PAT_FOR_TAGGING }} 106 | publish: 107 | runs-on: ubuntu-latest 108 | needs: 109 | - add_tag 110 | if: needs.add_tag.result == 'success' 111 | steps: 112 | - name: Check out 113 | uses: actions/checkout@v3 114 | - name: Setup .Net 115 | uses: actions/setup-dotnet@v3 116 | with: 117 | dotnet-version: 7.0.201 118 | - name: Restore 119 | run: dotnet restore 120 | - name: Build 121 | run: dotnet build --no-restore --configuration Release 122 | - name: Pack NuGet Package 123 | run: dotnet pack --configuration Release --include-symbols 124 | - name: Push NuGet Package 125 | run: dotnet nuget push **/bin/Release/**/*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_ACCESS }} --skip-duplicate 126 | -------------------------------------------------------------------------------- /LeVent.Infrastructure.Build/Services/ScriptGenerations/ScriptGenerationService.cs: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Organization: A coalition of the Good-Hearted Engineers 3 | // ---------------------------------------------------------------------------------- 4 | 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using ADotNet.Clients; 8 | using ADotNet.Models.Pipelines.GithubPipelines.DotNets; 9 | using ADotNet.Models.Pipelines.GithubPipelines.DotNets.Tasks; 10 | using ADotNet.Models.Pipelines.GithubPipelines.DotNets.Tasks.SetupDotNetTaskV3s; 11 | 12 | namespace LeVent.Infrastructure.Build.Services.ScriptGenerations 13 | { 14 | public class ScriptGenerationService 15 | { 16 | private readonly ADotNetClient adotNetClient; 17 | 18 | public ScriptGenerationService() => 19 | this.adotNetClient = new ADotNetClient(); 20 | 21 | public void GenerateBuildScript() 22 | { 23 | string branchName = "main"; 24 | 25 | var githubPipeline = new GithubPipeline 26 | { 27 | Name = "Build", 28 | 29 | OnEvents = new Events 30 | { 31 | Push = new PushEvent 32 | { 33 | Branches = new string[] { branchName } 34 | }, 35 | 36 | PullRequest = new PullRequestEvent 37 | { 38 | Branches = new string[] { branchName } 39 | } 40 | }, 41 | 42 | Jobs = new Dictionary 43 | { 44 | { 45 | "build", 46 | new Job 47 | { 48 | RunsOn = BuildMachines.UbuntuLatest, 49 | 50 | Steps = new List 51 | { 52 | new CheckoutTaskV3 53 | { 54 | Name = "Check out" 55 | }, 56 | 57 | new SetupDotNetTaskV3 58 | { 59 | Name = "Setup .Net", 60 | 61 | With = new TargetDotNetVersionV3 62 | { 63 | DotNetVersion = "7.0.201" 64 | } 65 | }, 66 | 67 | new RestoreTask 68 | { 69 | Name = "Restore" 70 | }, 71 | 72 | new DotNetBuildTask 73 | { 74 | Name = "Build" 75 | }, 76 | 77 | new TestTask 78 | { 79 | Name = "Test" 80 | } 81 | } 82 | } 83 | }, 84 | { 85 | "add_tag", 86 | new TagJob( 87 | runsOn: BuildMachines.UbuntuLatest, 88 | dependsOn: "build", 89 | projectRelativePath: "LeVent/LeVent.csproj", 90 | githubToken: "${{ secrets.PAT_FOR_TAGGING }}", 91 | branchName: branchName) 92 | }, 93 | { 94 | "publish", 95 | new PublishJob( 96 | runsOn: BuildMachines.UbuntuLatest, 97 | dependsOn: "add_tag", 98 | nugetApiKey: "${{ secrets.NUGET_ACCESS }}") 99 | } 100 | } 101 | }; 102 | 103 | string buildScriptPath = "../../../../.github/workflows/dotnet.yml"; 104 | string directoryPath = Path.GetDirectoryName(buildScriptPath); 105 | 106 | if (!Directory.Exists(directoryPath)) 107 | { 108 | Directory.CreateDirectory(directoryPath); 109 | } 110 | 111 | this.adotNetClient.SerializeAndWriteToFile(githubPipeline, path: buildScriptPath); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /LeVent/Clients/LeventClient.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | 6 | using System; 7 | using System.Threading.Tasks; 8 | using LeVent.Brokers.Storages; 9 | using LeVent.Models.Clients.Exceptions; 10 | using LeVent.Models.Foundations.Events.Exceptions; 11 | using LeVent.Models.Processings.Events.Exceptions; 12 | using LeVent.Services.Foundations.EventRegistrations; 13 | using LeVent.Services.Processings.Events; 14 | using Xeptions; 15 | 16 | namespace LeVent.Clients 17 | { 18 | public class LeVentClient : ILeVentClient 19 | { 20 | private readonly IEventProcessingService eventProcessingService; 21 | 22 | public LeVentClient() 23 | { 24 | IStorageBroker storageBroker = 25 | new StorageBroker(); 26 | 27 | IEventHandlerRegistrationService registrationService = 28 | new EventHandlerRegistrationService(storageBroker); 29 | 30 | this.eventProcessingService = 31 | new EventProcessingService(registrationService); 32 | } 33 | 34 | public async ValueTask PublishEventAsync(T @event, string eventName = null) 35 | { 36 | try 37 | { 38 | await this.eventProcessingService.PublishEventAsync(@event, eventName); 39 | } 40 | catch (EventProcessingValidationException eventProcessingValidationException) 41 | { 42 | throw CreateLeVentValidationException(eventProcessingValidationException); 43 | } 44 | catch (EventProcessingDependencyValidationException eventProcessingDependencyValidationException) 45 | { 46 | throw CreateLeVentValidationException(eventProcessingDependencyValidationException); 47 | } 48 | catch (EventProcessingDependencyException eventProcessingDependencyException) 49 | { 50 | throw CreateLeVentDependencyException(eventProcessingDependencyException); 51 | } 52 | catch (EventProcessingServiceException eventProcessingServiceException) 53 | { 54 | throw CreateLeVentServiceException(eventProcessingServiceException); 55 | } 56 | } 57 | 58 | public void RegisterEventHandler(Func eventHandler, string eventName = null) 59 | { 60 | try 61 | { 62 | this.eventProcessingService.AddEventHandler(eventHandler, eventName); 63 | } 64 | catch (EventProcessingValidationException eventProcessingValidationException) 65 | { 66 | throw CreateLeVentValidationException(eventProcessingValidationException); 67 | } 68 | catch (EventProcessingDependencyValidationException eventProcessingDependencyValidationException) 69 | { 70 | throw CreateLeVentValidationException(eventProcessingDependencyValidationException); 71 | } 72 | catch (EventProcessingDependencyException eventProcessingDependencyException) 73 | { 74 | throw CreateLeVentDependencyException(eventProcessingDependencyException); 75 | } 76 | catch (EventProcessingServiceException eventProcessingServiceException) 77 | { 78 | throw CreateLeVentServiceException(eventProcessingServiceException); 79 | } 80 | } 81 | 82 | private static LeVentValidationException CreateLeVentValidationException(Xeption innerException) 83 | { 84 | return new LeVentValidationException( 85 | message: "LeVent validation error occurred, fix errors and try again.", 86 | innerException: innerException); 87 | } 88 | 89 | private static LeVentDependencyException CreateLeVentDependencyException(Xeption innerException) 90 | { 91 | return new LeVentDependencyException( 92 | message: "LeVent dependency error occurred, contact support.", 93 | innerException: innerException); 94 | } 95 | 96 | private static LeVentServiceException CreateLeVentServiceException(Xeption innerException) 97 | { 98 | return new LeVentServiceException( 99 | message: "LeVent service error occurred, fix errors and try again.", 100 | innerException: innerException); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Foundations/EventHandlerRegistrations/EventsRegistrationServiceTests.Validations.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using FluentAssertions; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 9 | using Moq; 10 | using Xunit; 11 | 12 | namespace LeVent.Tests.Unit.Services.Foundations.EventHandlerRegistrations 13 | { 14 | public partial class EventHandlerRegistrationServiceTests 15 | { 16 | [Fact] 17 | private void ShouldThrowValidationExceptionOnAddIfEventRegistrationHandlerIsNull() 18 | { 19 | // given 20 | EventHandlerRegistration nullEventHandler = null; 21 | 22 | var nullEventHandlerException = 23 | new NullEventHandlerRegistrationException( 24 | message: "Event handler is null"); 25 | 26 | var expectedEventHandlerRegistrationValidationException = 27 | new EventHandlerRegistrationValidationException( 28 | message: "Event validation error occurred, please fix error and try again.", 29 | innerException: nullEventHandlerException); 30 | 31 | // when 32 | Action addEventHandlerRegistrationAction = () => 33 | this.eventHandlerRegistrationService.AddEventHandlerRegistation( 34 | nullEventHandler); 35 | 36 | EventHandlerRegistrationValidationException 37 | actualEventHandlerRegistrationValidationException = 38 | Assert.Throws( 39 | addEventHandlerRegistrationAction); 40 | 41 | // then 42 | actualEventHandlerRegistrationValidationException.Should() 43 | .BeEquivalentTo(expectedEventHandlerRegistrationValidationException); 44 | 45 | this.storageBrokerMock.Verify(broker => 46 | broker.InsertEventHandlerRegistration( 47 | It.IsAny>()), 48 | Times.Never); 49 | 50 | this.storageBrokerMock.VerifyNoOtherCalls(); 51 | } 52 | 53 | [Fact] 54 | private void ShouldThrowValidationExceptionOnAddIfEventHandlerIsNull() 55 | { 56 | // given 57 | EventHandlerRegistration randomEventHandlerRegistration = 58 | CreateRandomEventHandlerRegistration(); 59 | 60 | EventHandlerRegistration invalidEventHandlerRegistration = 61 | randomEventHandlerRegistration; 62 | 63 | invalidEventHandlerRegistration.EventHandler = null; 64 | 65 | var invalidEventHandlerRegistrationException = 66 | new InvalidEventHandlerRegistrationException( 67 | message: "Invalid event handler registration error ocurred, fix errors and try again."); 68 | 69 | invalidEventHandlerRegistrationException.AddData( 70 | key: nameof(EventHandlerRegistration.EventHandler), 71 | values: "Handler is required"); 72 | 73 | var expectedEventHandlerRegistrationValidationException = 74 | new EventHandlerRegistrationValidationException( 75 | message: "Event validation error occurred, please fix error and try again.", 76 | innerException: invalidEventHandlerRegistrationException); 77 | 78 | // when 79 | Action addEventHandlerRegistrationAction = () => 80 | this.eventHandlerRegistrationService.AddEventHandlerRegistation( 81 | invalidEventHandlerRegistration); 82 | 83 | EventHandlerRegistrationValidationException 84 | actualEventHandlerRegistrationValidationException = 85 | Assert.Throws( 86 | addEventHandlerRegistrationAction); 87 | 88 | // then 89 | actualEventHandlerRegistrationValidationException.Should() 90 | .BeEquivalentTo(expectedEventHandlerRegistrationValidationException); 91 | 92 | this.storageBrokerMock.Verify(broker => 93 | broker.InsertEventHandlerRegistration( 94 | It.IsAny>()), 95 | Times.Never); 96 | 97 | this.storageBrokerMock.VerifyNoOtherCalls(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Linq.Expressions; 9 | using System.Threading.Tasks; 10 | using KellermanSoftware.CompareNetObjects; 11 | using LeVent.Models.Foundations.EventHandlerRegistrations; 12 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 13 | using LeVent.Services.Foundations.EventRegistrations; 14 | using LeVent.Services.Processings.Events; 15 | using Moq; 16 | using Tynamix.ObjectFiller; 17 | using Xeptions; 18 | using Xunit; 19 | 20 | namespace LeVent.Tests.Unit.Services.Foundations.Events 21 | { 22 | public partial class EventProcessingServiceTests 23 | { 24 | private readonly Mock> eventHandlerRegistrationServiceMock; 25 | private readonly ICompareLogic compareLogic; 26 | private readonly IEventProcessingService eventProcessingService; 27 | 28 | public EventProcessingServiceTests() 29 | { 30 | this.eventHandlerRegistrationServiceMock = 31 | new Mock>(); 32 | 33 | this.compareLogic = new CompareLogic(); 34 | 35 | this.eventProcessingService = 36 | new EventProcessingService( 37 | eventHandlerRegistrationService: this.eventHandlerRegistrationServiceMock.Object); 38 | } 39 | 40 | public static TheoryData DependencyValidationExceptions() 41 | { 42 | var nullEventHandlerRegistrationException = 43 | new NullEventHandlerRegistrationException( 44 | message: "Event handler is null"); 45 | 46 | return new TheoryData 47 | { 48 | new EventHandlerRegistrationValidationException( 49 | message: "Event validation error occurred, please fix error and try again.", 50 | innerException: nullEventHandlerRegistrationException) 51 | }; 52 | } 53 | 54 | public static TheoryData DependencyExceptions() 55 | { 56 | var someInnerException = 57 | new Xeption(); 58 | 59 | return new TheoryData 60 | { 61 | new EventHandlerRegistrationServiceException( 62 | message: "Event service error occurred, contact support.", 63 | innerException: someInnerException) 64 | }; 65 | } 66 | 67 | private static List> CreateEventHandlerRegistrationsFromMocks( 68 | List>> eventHandlerMocks, 69 | string eventName = null) 70 | { 71 | return eventHandlerMocks.Select(eventHandlerMock => 72 | { 73 | return new EventHandlerRegistration 74 | { 75 | EventHandler = eventHandlerMock.Object, 76 | EventName = eventName 77 | }; 78 | }).ToList(); 79 | } 80 | 81 | private Expression, bool>> SameEventHandlerRegistrationAs( 82 | EventHandlerRegistration expectedEventHandlerRegistration) 83 | { 84 | return actualEventHandlerRegistration => 85 | this.compareLogic.Compare(expectedEventHandlerRegistration, actualEventHandlerRegistration) 86 | .AreEqual; 87 | } 88 | 89 | private static List>> CreateRandomEventHandlerMocks() 90 | { 91 | int randomCount = GetRandomNumber(); 92 | 93 | return Enumerable.Range(start: 0, count: randomCount) 94 | .Select(_ => new Mock>()) 95 | .ToList(); 96 | } 97 | 98 | private static int GetRandomNumber() => 99 | new IntRange(min: 2, max: 10).GetValue(); 100 | 101 | private static string GetRandomEventName() => 102 | new MnemonicString().GetValue(); 103 | 104 | private static Filler> CreateEventHandlerRegistrationFiller() 105 | { 106 | var filler = new Filler>(); 107 | 108 | filler.Setup() 109 | .OnProperty(registrationHandler => registrationHandler.EventHandler) 110 | .Use(new Mock>().Object); 111 | 112 | return filler; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /LeVent/Services/Processings/Events/EventProcessingService.Exceptions.cs: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ---------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using LeVent.Models.Foundations.EventHandlerRegistrations.Exceptions; 8 | using LeVent.Models.Foundations.Events.Exceptions; 9 | using LeVent.Models.Processings.Events.Exceptions; 10 | using Xeptions; 11 | 12 | namespace LeVent.Services.Processings.Events 13 | { 14 | public partial class EventProcessingService 15 | { 16 | private delegate void ReturningNothingFunction(); 17 | private delegate ValueTask ReturningValueTaskFunction(); 18 | 19 | private void TryCatch(ReturningNothingFunction returningNothingFunction) 20 | { 21 | try 22 | { 23 | returningNothingFunction(); 24 | } 25 | catch (NullEventHandlerProcessingException nullEventHandlerProcessingException) 26 | { 27 | throw CreateEventProcessingValidationException(nullEventHandlerProcessingException); 28 | } 29 | catch (EventHandlerRegistrationValidationException eventHandlerRegistrationValidationException) 30 | { 31 | throw CreateEventProcessingDependencyValidationException( 32 | eventHandlerRegistrationValidationException.InnerException as Xeption); 33 | } 34 | catch (EventHandlerRegistrationServiceException eventHandlerRegistrationServiceException) 35 | { 36 | throw CreateEventProcessingDependencyException( 37 | eventHandlerRegistrationServiceException.InnerException as Xeption); 38 | } 39 | catch (Exception exception) 40 | { 41 | var failedEventProcessingServiceException = 42 | new FailedEventProcessingServiceException( 43 | message: "Failed event service error ocurred, contact support.", 44 | innerException: exception); 45 | 46 | throw CreateEventProcessingServiceException( 47 | failedEventProcessingServiceException); 48 | } 49 | } 50 | 51 | private async ValueTask TryCatch(ReturningValueTaskFunction returningValueTaskFunction) 52 | { 53 | try 54 | { 55 | await returningValueTaskFunction(); 56 | } 57 | catch (NullEventProcessingException nullEventProcessingException) 58 | { 59 | throw CreateEventProcessingValidationException(nullEventProcessingException); 60 | } 61 | catch (Exception exception) 62 | { 63 | var failedEventProcessingServiceException = 64 | new FailedEventProcessingServiceException( 65 | message: "Failed event service error ocurred, contact support.", 66 | innerException: exception); 67 | 68 | throw CreateEventProcessingServiceException( 69 | failedEventProcessingServiceException); 70 | } 71 | } 72 | 73 | private static EventProcessingValidationException CreateEventProcessingValidationException( 74 | Xeption innerException) 75 | { 76 | return new EventProcessingValidationException( 77 | message: "Event validation error occurred, please fix error and try again.", 78 | innerException: innerException); 79 | } 80 | 81 | private static EventProcessingDependencyValidationException CreateEventProcessingDependencyValidationException( 82 | Xeption innerException) 83 | { 84 | return new EventProcessingDependencyValidationException( 85 | message: "Event validation error occurred, please fix error and try again.", 86 | innerException: innerException); 87 | } 88 | 89 | private static EventProcessingDependencyException CreateEventProcessingDependencyException( 90 | Xeption innerException) 91 | { 92 | return new EventProcessingDependencyException( 93 | message: "Event error occurred, please fix error and try again.", 94 | innerException: innerException); 95 | } 96 | 97 | private static EventProcessingServiceException CreateEventProcessingServiceException( 98 | Xeption innerException) 99 | { 100 | return new EventProcessingServiceException( 101 | message: "Event service error occurred, contact support.", 102 | innerException: innerException); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Logic.Publish.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using LeVent.Models.Foundations.EventHandlerRegistrations; 10 | using Moq; 11 | using Xunit; 12 | 13 | namespace LeVent.Tests.Unit.Services.Foundations.Events 14 | { 15 | public partial class EventProcessingServiceTests 16 | { 17 | [Fact] 18 | private async Task ShouldPublishEventWithoutEventNameAsync() 19 | { 20 | // given 21 | List>> randomEventHandlerMocks = 22 | CreateRandomEventHandlerMocks(); 23 | 24 | List> randomEventHandlerRegistrations = 25 | CreateEventHandlerRegistrationsFromMocks(randomEventHandlerMocks); 26 | 27 | List> retrievedEventHandlerRegistrations = 28 | randomEventHandlerRegistrations; 29 | 30 | this.eventHandlerRegistrationServiceMock.Setup(service => 31 | service.RetrieveAllEventHandlerRegistrations()) 32 | .Returns(retrievedEventHandlerRegistrations); 33 | 34 | var randomEvent = new object(); 35 | object inputEvent = randomEvent; 36 | 37 | // when 38 | await this.eventProcessingService.PublishEventAsync(inputEvent); 39 | 40 | // then 41 | randomEventHandlerMocks.ForEach(eventHandlerMock => 42 | eventHandlerMock.Verify(eventHandler => 43 | eventHandler(inputEvent), 44 | Times.Once)); 45 | 46 | this.eventHandlerRegistrationServiceMock.Verify(service => 47 | service.RetrieveAllEventHandlerRegistrations(), 48 | Times.Once); 49 | 50 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 51 | } 52 | 53 | [Fact] 54 | private async Task ShouldPublishEventWithEventNameAsync() 55 | { 56 | // given 57 | string randomEventName = GetRandomEventName(); 58 | string inputEventName = randomEventName; 59 | 60 | List>> randomCalledEventHandlerMocks = 61 | CreateRandomEventHandlerMocks(); 62 | 63 | List>> randomNonCalledEventHandlerMocks = 64 | CreateRandomEventHandlerMocks(); 65 | 66 | List> randomTargetEventHandlerRegistrations = 67 | CreateEventHandlerRegistrationsFromMocks( 68 | randomCalledEventHandlerMocks, 69 | inputEventName); 70 | 71 | List> randomNonTargetEventHandlerRegistrations = 72 | CreateEventHandlerRegistrationsFromMocks( 73 | randomNonCalledEventHandlerMocks); 74 | 75 | List> retrievedTargetEventHandlerRegistrations = 76 | randomTargetEventHandlerRegistrations; 77 | 78 | List> retrievedNonTargetEventHandlerRegistrations = 79 | randomNonTargetEventHandlerRegistrations; 80 | 81 | List> retrievedAllEventHandlerRegistrations = 82 | retrievedTargetEventHandlerRegistrations.Concat( 83 | retrievedNonTargetEventHandlerRegistrations) 84 | .ToList(); 85 | 86 | this.eventHandlerRegistrationServiceMock.Setup(service => 87 | service.RetrieveAllEventHandlerRegistrations()) 88 | .Returns(retrievedAllEventHandlerRegistrations); 89 | 90 | var randomEvent = new object(); 91 | object inputEvent = randomEvent; 92 | 93 | // when 94 | await this.eventProcessingService.PublishEventAsync( 95 | inputEvent, 96 | inputEventName); 97 | 98 | // then 99 | randomCalledEventHandlerMocks.ForEach(eventHandlerMock => 100 | eventHandlerMock.Verify(eventHandler => 101 | eventHandler(inputEvent), 102 | Times.Once)); 103 | 104 | randomNonCalledEventHandlerMocks.ForEach(eventHandlerMock => 105 | eventHandlerMock.Verify(eventHandler => 106 | eventHandler(inputEvent), 107 | Times.Never)); 108 | 109 | this.eventHandlerRegistrationServiceMock.Verify(service => 110 | service.RetrieveAllEventHandlerRegistrations(), 111 | Times.Once); 112 | 113 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /LeVent.Tests.Unit/Services/Processings/Events/EventProcessingServiceTests.Exceptions.Add.cs: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------- 2 | // Copyright (c) The Standard Community, a coalition of the Good-Hearted Engineers 3 | // ------------------------------------------------------------------------------- 4 | 5 | using System; 6 | using System.Threading.Tasks; 7 | using FluentAssertions; 8 | using LeVent.Models.Foundations.EventHandlerRegistrations; 9 | using LeVent.Models.Foundations.Events.Exceptions; 10 | using LeVent.Models.Processings.Events.Exceptions; 11 | using Moq; 12 | using Xeptions; 13 | using Xunit; 14 | 15 | namespace LeVent.Tests.Unit.Services.Foundations.Events 16 | { 17 | public partial class EventProcessingServiceTests 18 | { 19 | [Theory] 20 | [MemberData(nameof(DependencyValidationExceptions))] 21 | private void ShouldThrowDependencyValidationExceptionOnAddIfDependencyValidationErrorOccurs( 22 | Xeption dependencyValidationException) 23 | { 24 | // given 25 | var eventHandlerMock = 26 | new Mock>(); 27 | 28 | Func someEventHandler = 29 | eventHandlerMock.Object; 30 | 31 | var expectedEventProcessingDependencyValidationException = 32 | new EventProcessingDependencyValidationException( 33 | message: "Event validation error occurred, please fix error and try again.", 34 | innerException: dependencyValidationException.InnerException as Xeption); 35 | 36 | this.eventHandlerRegistrationServiceMock.Setup(service => 37 | service.AddEventHandlerRegistation( 38 | It.IsAny>())) 39 | .Throws(dependencyValidationException); 40 | 41 | // when 42 | Action addEventHandlerAction = () => 43 | this.eventProcessingService.AddEventHandler(someEventHandler); 44 | 45 | EventProcessingDependencyValidationException 46 | actualEventProcessingDependencyValidationException = 47 | Assert.Throws( 48 | addEventHandlerAction); 49 | 50 | // then 51 | actualEventProcessingDependencyValidationException.Should() 52 | .BeEquivalentTo(expectedEventProcessingDependencyValidationException); 53 | 54 | this.eventHandlerRegistrationServiceMock.Verify(service => 55 | service.AddEventHandlerRegistation( 56 | It.IsAny>()), 57 | Times.Once); 58 | 59 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 60 | } 61 | 62 | [Theory] 63 | [MemberData(nameof(DependencyExceptions))] 64 | private void ShouldThrowDependencyExceptionOnAddIfDependencyErrorOccurs( 65 | Xeption dependencyException) 66 | { 67 | // given 68 | var eventHandlerMock = 69 | new Mock>(); 70 | 71 | Func someEventHandler = 72 | eventHandlerMock.Object; 73 | 74 | var expectedEventProcessingDependencyException = 75 | new EventProcessingDependencyException( 76 | message: "Event error occurred, please fix error and try again.", 77 | innerException: dependencyException.InnerException as Xeption); 78 | 79 | this.eventHandlerRegistrationServiceMock.Setup(service => 80 | service.AddEventHandlerRegistation( 81 | It.IsAny>())) 82 | .Throws(dependencyException); 83 | 84 | // when 85 | Action addEventHandlerAction = () => 86 | this.eventProcessingService.AddEventHandler(someEventHandler); 87 | 88 | EventProcessingDependencyException 89 | actualEventProcessingDependencyException = 90 | Assert.Throws( 91 | addEventHandlerAction); 92 | 93 | // then 94 | actualEventProcessingDependencyException.Should() 95 | .BeEquivalentTo(expectedEventProcessingDependencyException); 96 | 97 | this.eventHandlerRegistrationServiceMock.Verify(service => 98 | service.AddEventHandlerRegistation( 99 | It.IsAny>()), 100 | Times.Once); 101 | 102 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 103 | } 104 | 105 | [Fact] 106 | private void ShouldThrowServiceExceptionOnAddIfServiceErrorOcurrs() 107 | { 108 | // given 109 | var eventHandlerMock = 110 | new Mock>(); 111 | 112 | Func someEventHandler = 113 | eventHandlerMock.Object; 114 | 115 | var serviceException = new Exception(); 116 | 117 | var failedEventProcessingServiceException = 118 | new FailedEventProcessingServiceException( 119 | message: "Failed event service error ocurred, contact support.", 120 | innerException: serviceException); 121 | 122 | var expectedEventServiceException = 123 | new EventProcessingServiceException( 124 | message: "Event service error occurred, contact support.", 125 | innerException: failedEventProcessingServiceException); 126 | 127 | this.eventHandlerRegistrationServiceMock.Setup(service => 128 | service.AddEventHandlerRegistation( 129 | It.IsAny>())) 130 | .Throws(serviceException); 131 | 132 | // when 133 | Action addEventHandlerAction = () => 134 | this.eventProcessingService.AddEventHandler(someEventHandler); 135 | 136 | EventProcessingServiceException actualEventProcessingServiceException = 137 | Assert.Throws(addEventHandlerAction); 138 | 139 | // then 140 | actualEventProcessingServiceException.Should() 141 | .BeEquivalentTo(expectedEventServiceException); 142 | 143 | this.eventHandlerRegistrationServiceMock.Verify(service => 144 | service.AddEventHandlerRegistation( 145 | It.IsAny>()), 146 | Times.Once); 147 | 148 | this.eventHandlerRegistrationServiceMock.VerifyNoOtherCalls(); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![LeVent](https://raw.githubusercontent.com/The-Standard-Organization/LeVent/main/LeVent/Resources/Images/LeVent_git_logo.png) 2 | 3 | [![Build](https://github.com/The-Standard-Organization/LeVent/actions/workflows/dotnet.yml/badge.svg)](https://github.com/The-Standard-Organization/LeVent/actions/workflows/dotnet.yml) 4 | [![Nuget](https://img.shields.io/nuget/v/LeVent?logo=nuget)](https://www.nuget.org/packages/LeVent/) 5 | ![Nuget](https://img.shields.io/nuget/dt/LeVent?color=blue&label=Downloads) 6 | [![The Standard](https://img.shields.io/github/v/release/hassanhabib/The-Standard?filter=v2.10.1&style=default&label=Standard%20Version&color=2ea44f)](https://github.com/hassanhabib/The-Standard/tree/2.10.1) 7 | [![The Standard - COMPLIANT](https://img.shields.io/badge/The_Standard-COMPLIANT-2ea44f)](https://github.com/hassanhabib/The-Standard) 8 | [![The Standard Community](https://img.shields.io/discord/934130100008538142?color=%237289da&label=The%20Standard%20Community&logo=Discord)](https://discord.gg/vdPZ7hS52X) 9 | 10 | # LeVent 11 | LeVent is a simple .NET library designed to provide a local event subscribing/publishing capabilities to .NET developers. 12 | 13 | ## Standard-Compliance 14 | This library was built according to The Standard. The library follows engineering principles, patterns and tooling as recommended by The Standard. 15 | 16 | This library is also a community effort which involved many nights of pair-programming, test-driven development and in-depth exploration research and design discussions. 17 | 18 | ## Standard-Promise 19 | The most important fulfillment aspect in a Standard complaint system is aimed towards contributing to people, its evolution, and principles. 20 | An organization that systematically honors an environment of learning, training, and sharing knowledge is an organization that learns from the past, makes calculated risks for the future, 21 | and brings everyone within it up to speed on the current state of things as honestly, rapidly, and efficiently as possible. 22 | 23 | We believe that everyone has the right to privacy, and will never do anything that could violate that right. 24 | We are committed to writing ethical and responsible software, and will always strive to use our skills, coding, and systems for the good. 25 | We believe that these beliefs will help to ensure that our software(s) are safe and secure and that it will never be used to harm or collect personal data for malicious purposes. 26 | 27 | The Standard Community as a promise to you is in upholding these values. 28 | 29 | ## How it Works 30 | Understanding the ideas around the [Cul-De-Sac pattern](https://www.youtube.com/watch?v=Wgz5m0MY9Xo&ab_channel=HassanHabib) is essential for taking advantage of LeVent. 31 | 32 | Assume that you have multiple Foundation Services that want to be notified when an event occurs. You can create a simple `EventBroker` that leverages LeVent to offer the registration and publishing capabilities as follows: 33 | 34 | ![image](https://user-images.githubusercontent.com/1453985/193402310-3e7e0617-f04c-4187-a381-5ad6e7936573.png) 35 | 36 | In the figure above, the `EventBroker` leverages LeVent to offer subscribing and publishing capabilities as follows: 37 | 38 | ```csharp 39 | public ILeVentClient StudentEventClient { get; set; } 40 | 41 | public async ValueTask PublishStudentEventAsync(Student student) => 42 | await this.StudentEventClient.PublishEventAsync(student); 43 | 44 | public void RegisterStudentHandler(Func studentHandler) => 45 | this.StudentEventClient.RegisterEventHandler(studentHandler); 46 | ``` 47 | 48 | Then, a `StudentEventService` will leverage the `EventBroker` to allow higher-order services to register/listen or publish through that eventing mechanism as follows: 49 | 50 | ```csharp 51 | public class StudentEventService : IStudentEventService 52 | { 53 | private readonly IEventBroker eventBroker; 54 | 55 | public StudentEventService(IEventBroker eventBroker) => 56 | this.eventBroker = eventBroker; 57 | 58 | public async ValueTask PublishStudentEventAsync(Student student) => 59 | await this.eventBroker.PublishStudentEventAsync(student); 60 | 61 | public void RegisterStudentEventHandler(Func studentEventHandler) => 62 | this.eventBroker.RegisterStudentHandler(studentEventHandler); 63 | } 64 | 65 | ``` 66 | 67 | The next step is for Orchestration services to publish or listen to the event and call its dependencies. 68 | 69 | In the case of a publisher - a `StudentOrchestrationService` would be as follows: 70 | 71 | ```csharp 72 | public class StudentOrchestrationService : IStudentOrchestrationService 73 | { 74 | private readonly IStudentEventService studentEventService; 75 | private readonly IStudentService studentService; 76 | 77 | public StudentOrchestrationService( 78 | IStudentEventService studentEventService, 79 | IStudentService studentService) 80 | { 81 | this.studentEventService = studentEventService; 82 | this.studentService = studentService; 83 | } 84 | 85 | public async ValueTask AddStudentAsync(Student student) 86 | { 87 | this.studentService.AddStudent(student); 88 | await this.studentEventService.PublishStudentEventAsync(student); 89 | } 90 | } 91 | ``` 92 | The Orchestration service above will first add a `Student` and then publish an event about that student for all listeners. 93 | 94 | Let's check out what a listener would look like: 95 | 96 | ```csharp 97 | public class StudentLibraryOrchestrationService : IStudentLibraryOrchestrationService 98 | { 99 | private readonly IStudentEventService studentEventService; 100 | private readonly IStudentLibraryService studentLibraryService; 101 | 102 | public StudentLibraryOrchestrationService( 103 | IStudentEventService studentEventService, 104 | IStudentLibraryService studentLibraryService) 105 | { 106 | this.studentEventService = studentEventService; 107 | this.studentLibraryService = studentLibraryService; 108 | } 109 | 110 | public void ListenToStudentEvents() 111 | { 112 | this.studentEventService.RegisterStudentEventHandler((student) => 113 | { 114 | this.studentLibraryService.RegisterStudentLibaryCard(student); 115 | 116 | return ValueTask.CompletedTask; 117 | }); 118 | } 119 | ``` 120 | 121 | The `StudentLibraryOrchestrationService` will receive a `Student` event from whoever is publishing these events without coupling and act upon that very same event by creating a `LibraryCard`. 122 | 123 | This pattern is called [Cul-De-Sac](https://github.com/hassanhabib/The-Standard/blob/master/2.%20Services/2.3%20Orchestrations/2.3%20Orchestrations.md#2322-cul-de-sac). It's an advanced low-level architecture technique to allow scaling and chaining to infinite number of events with no coupling whatsoever - here's how it looks in the 3D space: 124 | 125 | 126 | ![image](https://user-images.githubusercontent.com/1453985/193402672-062e7db2-7e47-4b50-bbd6-a376b198814c.png) 127 | 128 | The figure above assumes no dependence between one listener and the other. You can also leverage LeVent to allow the chaining of listeners as follows: 129 | 130 | ![image](https://user-images.githubusercontent.com/1453985/193402792-7e808de6-d649-4766-bcda-a29448fe8571.png) 131 | 132 | These patterns allow for more maintainable standardized systems wholly decoupled from their event source and capable of passing forward an event as an interceptor or completing a task and forwarding. 133 | 134 | 135 | Here's the Low-Level Architecture of this library 136 | 137 | ![image](https://user-images.githubusercontent.com/1453985/194765922-b5c0f67b-79f0-49b1-80ba-8fffc4546c7c.png) 138 | 139 | If you have any suggestions, comments or questions, please feel free to contact me on: 140 | 141 | [Twitter](https://twitter.com/hassanrezkhabib) 142 | 143 | [LinkedIn](https://www.linkedin.com/in/hassanrezkhabib/) 144 | 145 | [E-Mail](mailto:hassanhabib@live.com) 146 | 147 | ### Important Notice 148 | Special thanks to all the contributors that make this project a success. A special thanks to Mr. Hassan Habib and Mr. Kailu Hu for their dedicated contribution. 149 | --------------------------------------------------------------------------------