Repository: ivanpaulovich/FluentMediator Branch: master Commit: 6f1c0a53d332 Files: 103 Total size: 142.2 KB Directory structure: gitextract_qjfzijxk/ ├── .all-contributorsrc ├── .editorconfig ├── .gitignore ├── .vscode/ │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── FluentMediator.sln ├── LICENSE ├── README.md ├── azure-pipelines-1.yml ├── azure-pipelines.yml ├── changelog.md ├── docs/ │ └── icon.xcf ├── samples/ │ ├── AspNetCore/ │ │ ├── .vscode/ │ │ │ ├── launch.json │ │ │ └── tasks.json │ │ ├── Wallet.sln │ │ ├── src/ │ │ │ ├── Core/ │ │ │ │ ├── Core.csproj │ │ │ │ ├── Services/ │ │ │ │ │ └── ICustomerRepository.cs │ │ │ │ ├── UseCases/ │ │ │ │ │ ├── IRegisterUseCase.cs │ │ │ │ │ ├── Register.cs │ │ │ │ │ ├── RegisterCommand.cs │ │ │ │ │ └── RegisterResponse.cs │ │ │ │ └── Wallet/ │ │ │ │ └── Customer.cs │ │ │ ├── Infrastructure/ │ │ │ │ ├── InMemory/ │ │ │ │ │ └── CustomerRepository.cs │ │ │ │ └── Infrastructure.csproj │ │ │ └── WebApi/ │ │ │ ├── Controllers/ │ │ │ │ └── Register/ │ │ │ │ ├── CustomersController.cs │ │ │ │ └── RegisterRequest.cs │ │ │ ├── Program.cs │ │ │ ├── Startup.cs │ │ │ ├── WebApi.csproj │ │ │ ├── appsettings.Development.json │ │ │ └── appsettings.json │ │ └── test/ │ │ └── UnitTests/ │ │ ├── UnitTests.csproj │ │ └── UseCasesTests/ │ │ └── RegisterTests.cs │ └── SimpleConsoleApp/ │ ├── .vscode/ │ │ ├── launch.json │ │ ├── settings.json │ │ └── tasks.json │ ├── PingPong/ │ │ ├── PingHandler.cs │ │ ├── PingPong.csproj │ │ ├── PingRequest.cs │ │ └── Program.cs │ └── Samples.sln ├── src/ │ ├── FluentMediator/ │ │ ├── FluentMediator.csproj │ │ ├── GetService.cs │ │ ├── IMediator.cs │ │ ├── IPipelineProvider.cs │ │ ├── IPipelineProviderBuilder.cs │ │ ├── Mediator.cs │ │ ├── MediatorException.cs │ │ ├── NullRequestException.cs │ │ ├── PipelineNotFoundEventArgs.cs │ │ ├── PipelineProvider.cs │ │ ├── PipelineProviderBuilder.cs │ │ └── Pipelines/ │ │ ├── CancellablePipelineAsync/ │ │ │ ├── Direct.cs │ │ │ ├── ICancellableMediator.cs │ │ │ ├── ICancellablePipelineAsync.cs │ │ │ ├── ICancellablePipelineAsyncBuilder.cs │ │ │ ├── ICancellablePipelineProvider.cs │ │ │ ├── ICancellablePipelineProviderBuilder.cs │ │ │ ├── IDirect.cs │ │ │ ├── Pipeline.cs │ │ │ └── PipelineBuilder.cs │ │ ├── IMethodCollection.cs │ │ ├── INamedPipeline.cs │ │ ├── IPipelineBehavior.cs │ │ ├── IPipelineCollection.cs │ │ ├── ITypedPipeline.cs │ │ ├── Method.cs │ │ ├── MethodCollection.cs │ │ ├── Pipeline/ │ │ │ ├── Direct.cs │ │ │ ├── IDirect.cs │ │ │ ├── IPipeline.cs │ │ │ ├── IPipelineBuilder.cs │ │ │ ├── ISyncMediator.cs │ │ │ ├── ISyncPipelineProvider.cs │ │ │ ├── ISyncPipelineProviderBuilder.cs │ │ │ ├── Pipeline.cs │ │ │ └── PipelineBuilder.cs │ │ ├── PipelineAlreadyExistsException.cs │ │ ├── PipelineAsync/ │ │ │ ├── Direct.cs │ │ │ ├── IAsyncMediator.cs │ │ │ ├── IAsyncPipelineProvider.cs │ │ │ ├── IAsyncPipelineProviderBuilder.cs │ │ │ ├── IDirect.cs │ │ │ ├── IPipelineAsync.cs │ │ │ ├── IPipelineAsyncBuilder.cs │ │ │ ├── Pipeline.cs │ │ │ └── PipelineBuilder.cs │ │ ├── PipelineBehavior.cs │ │ ├── PipelineCollection.cs │ │ ├── PipelineNotFoundException.cs │ │ └── ReturnFunctionIsNullException.cs │ └── FluentMediator.Microsoft.Extensions.DependencyInjection/ │ ├── FluentMediator.Microsoft.Extensions.DependencyInjection.csproj │ └── FluentMediatorExtensions.cs └── test/ └── UnitTests/ ├── BuildingMediatorTests.cs ├── MyCustomMediator.cs ├── PingPong/ │ ├── IPingHandler.cs │ ├── PingHandler.cs │ ├── PingRequest.cs │ └── PingResponse.cs ├── PublishingRequestsTests.cs ├── SendingRequestTests.cs └── UnitTests.csproj ================================================ FILE CONTENTS ================================================ ================================================ FILE: .all-contributorsrc ================================================ { "files": [ "README.md" ], "imageSize": 100, "commit": false, "contributors": [ { "login": "ivanpaulovich", "name": "Ivan Paulovich", "avatar_url": "https://avatars3.githubusercontent.com/u/7133698?v=4", "profile": "https://paulovich.net", "contributions": [ "code", "design", "test" ] }, { "login": "joacar", "name": "Joakim Carselind", "avatar_url": "https://avatars1.githubusercontent.com/u/439028?v=4", "profile": "http://www.carselind.se", "contributions": [ "review", "ideas" ] }, { "login": "vag1830", "name": "Vaggelis Mparmpas", "avatar_url": "https://avatars2.githubusercontent.com/u/1694870?v=4", "profile": "https://github.com/vag1830", "contributions": [ "test" ] } ], "contributorsPerLine": 7, "projectName": "FluentMediator", "projectOwner": "ivanpaulovich", "repoType": "github", "repoHost": "https://github.com" } ================================================ FILE: .editorconfig ================================================ # editorconfig.org # top-most EditorConfig file root = true # Default settings: # A newline ending every file # Use 4 spaces as indentation [*] insert_final_newline = true indent_style = space indent_size = 4 trim_trailing_whitespace = true [project.json] indent_size = 2 # C# files [*.cs] # New line preferences csharp_new_line_before_open_brace = all csharp_new_line_before_else = true csharp_new_line_before_catch = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_between_query_expression_clauses = true # Indentation preferences csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents = true csharp_indent_case_contents_when_block = true csharp_indent_switch_labels = true csharp_indent_labels = one_less_than_current # Modifier preferences csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion # avoid this. unless absolutely necessary dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_property = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_event = false:suggestion # Types: use keywords instead of BCL types, and permit var only when the type is clear csharp_style_var_for_built_in_types = false:suggestion csharp_style_var_when_type_is_apparent = false:none csharp_style_var_elsewhere = false:suggestion dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion # name all constant fields using PascalCase dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_style.pascal_case_style.capitalization = pascal_case # static fields should have s_ prefix dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style dotnet_naming_symbols.static_fields.applicable_kinds = field dotnet_naming_symbols.static_fields.required_modifiers = static dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected dotnet_naming_style.static_prefix_style.required_prefix = s_ dotnet_naming_style.static_prefix_style.capitalization = camel_case # internal and private fields should be _camelCase dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal dotnet_naming_style.camel_case_underscore_style.required_prefix = _ dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case # Code style defaults csharp_using_directive_placement = outside_namespace:suggestion dotnet_sort_system_directives_first = true csharp_prefer_braces = true:refactoring csharp_preserve_single_line_blocks = true:none csharp_preserve_single_line_statements = false:none csharp_prefer_static_local_function = true:suggestion csharp_prefer_simple_using_statement = false:none csharp_style_prefer_switch_expression = true:suggestion # Code quality dotnet_style_readonly_field = true:suggestion dotnet_code_quality_unused_parameters = non_public:suggestion # Expression-level preferences dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_auto_properties = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:refactoring dotnet_style_prefer_conditional_expression_over_return = true:refactoring csharp_prefer_simple_default_expression = true:suggestion # Expression-bodied members csharp_style_expression_bodied_methods = true:refactoring csharp_style_expression_bodied_constructors = true:refactoring csharp_style_expression_bodied_operators = true:refactoring csharp_style_expression_bodied_properties = true:refactoring csharp_style_expression_bodied_indexers = true:refactoring csharp_style_expression_bodied_accessors = true:refactoring csharp_style_expression_bodied_lambdas = true:refactoring csharp_style_expression_bodied_local_functions = true:refactoring # Pattern matching csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion # Null checking preferences csharp_style_throw_expression = true:suggestion csharp_style_conditional_delegate_call = true:suggestion # Other features csharp_style_prefer_index_operator = false:none csharp_style_prefer_range_operator = false:none csharp_style_pattern_local_over_anonymous_function = false:none # Space preferences csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true csharp_space_after_dot = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_after_semicolon_in_for_statement = true csharp_space_around_binary_operators = before_and_after csharp_space_around_declaration_statements = do_not_ignore csharp_space_before_colon_in_inheritance_clause = true csharp_space_before_comma = false csharp_space_before_dot = false csharp_space_before_open_square_brackets = false csharp_space_before_semicolon_in_for_statement = false csharp_space_between_empty_square_brackets = false csharp_space_between_method_call_empty_parameter_list_parentheses = false csharp_space_between_method_call_name_and_opening_parenthesis = false csharp_space_between_method_call_parameter_list_parentheses = false csharp_space_between_method_declaration_empty_parameter_list_parentheses = false csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_space_between_square_brackets = false # Analyzers dotnet_code_quality.ca1802.api_surface = private, internal # C++ Files [*.{cpp,h,in}] curly_bracket_next_line = true indent_brace_style = Allman # Xml project files [*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] indent_size = 2 # Xml build files [*.builds] indent_size = 2 # Xml files [*.{xml,stylecop,resx,ruleset}] indent_size = 2 # Xml config files [*.{props,targets,config,nuspec}] indent_size = 2 # Shell scripts [*.sh] end_of_line = lf [*.{cmd, bat}] end_of_line = crlf ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ **/Properties/launchSettings.json # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ .DS_Store ================================================ FILE: .vscode/launch.json ================================================ { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (console)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceFolder}/test/UnitTests/bin/Debug/netcoreapp3.0/UnitTests.dll", "args": [], "cwd": "${workspaceFolder}/test/UnitTests", // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console": "internalConsole", "stopAtEntry": false }, { "name": ".NET Core Attach", "type": "coreclr", "request": "attach", "processId": "${command:pickProcess}" } ] } ================================================ FILE: .vscode/settings.json ================================================ { "workbench.colorCustomizations": { "activityBar.background": "#2f7c47", "activityBar.activeBorder": "#422c74", "activityBar.foreground": "#e7e7e7", "activityBar.inactiveForeground": "#e7e7e799", "activityBarBadge.background": "#422c74", "activityBarBadge.foreground": "#e7e7e7", "titleBar.activeBackground": "#215732", "titleBar.inactiveBackground": "#21573299", "titleBar.activeForeground": "#e7e7e7", "titleBar.inactiveForeground": "#e7e7e799", "statusBar.background": "#215732", "statusBarItem.hoverBackground": "#2f7c47", "statusBar.foreground": "#e7e7e7" }, "peacock.color": "#215732" } ================================================ FILE: .vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "build", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/test/UnitTests/UnitTests.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "publish", "command": "dotnet", "type": "process", "args": [ "publish", "${workspaceFolder}/test/UnitTests/UnitTests.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "watch", "command": "dotnet", "type": "process", "args": [ "watch", "run", "${workspaceFolder}/test/UnitTests/UnitTests.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" } ] } ================================================ FILE: FluentMediator.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{2F50D282-F726-49F8-87B7-5662493EDBCA}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentMediator", "src\FluentMediator\FluentMediator.csproj", "{21CE6BEA-C0A5-4676-A56A-7574E1373A0E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{62742B03-49D2-429F-A928-3E6DCA724943}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{3F9FB7FC-68CA-451D-9828-323F20FB3DB7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentMediator.Microsoft.Extensions.DependencyInjection", "src\FluentMediator.Microsoft.Extensions.DependencyInjection\FluentMediator.Microsoft.Extensions.DependencyInjection.csproj", "{2E365BC8-38CB-4FAD-B186-85F053B2D53F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|x64.ActiveCfg = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|x64.Build.0 = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|x86.ActiveCfg = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Debug|x86.Build.0 = Debug|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|Any CPU.Build.0 = Release|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|x64.ActiveCfg = Release|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|x64.Build.0 = Release|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|x86.ActiveCfg = Release|Any CPU {21CE6BEA-C0A5-4676-A56A-7574E1373A0E}.Release|x86.Build.0 = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|x64.ActiveCfg = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|x64.Build.0 = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|x86.ActiveCfg = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Debug|x86.Build.0 = Debug|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|Any CPU.Build.0 = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|x64.ActiveCfg = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|x64.Build.0 = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|x86.ActiveCfg = Release|Any CPU {3F9FB7FC-68CA-451D-9828-323F20FB3DB7}.Release|x86.Build.0 = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|Any CPU.Build.0 = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|x64.ActiveCfg = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|x64.Build.0 = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|x86.ActiveCfg = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Debug|x86.Build.0 = Debug|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|Any CPU.ActiveCfg = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|Any CPU.Build.0 = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|x64.ActiveCfg = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|x64.Build.0 = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|x86.ActiveCfg = Release|Any CPU {2E365BC8-38CB-4FAD-B186-85F053B2D53F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {21CE6BEA-C0A5-4676-A56A-7574E1373A0E} = {2F50D282-F726-49F8-87B7-5662493EDBCA} {3F9FB7FC-68CA-451D-9828-323F20FB3DB7} = {62742B03-49D2-429F-A928-3E6DCA724943} {2E365BC8-38CB-4FAD-B186-85F053B2D53F} = {2F50D282-F726-49F8-87B7-5662493EDBCA} EndGlobalSection EndGlobal ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # FluentMediator [![Build Status](https://ivanpaulovich.visualstudio.com/FluentMediator/_apis/build/status/ivanpaulovich.FluentMediator?branchName=master)](https://ivanpaulovich.visualstudio.com/FluentMediator/_build/latest?definitionId=24&branchName=master) [![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors) ![GitHub issues](https://img.shields.io/github/issues/ivanpaulovich/FluentMediator) ![GitHub pull requests](https://img.shields.io/github/issues-pr/ivanpaulovich/FluentMediator) ![NuGet](https://buildstats.info/nuget/FluentMediator) :twisted_rightwards_arrows: We will not require you to add dependencies into your domain or to implement frameworks interfaces in your event handlers. Finally a really loosely coupled mediator library was born. ## Install ``` Install-Package FluentMediator ``` For seameless .NET Core integration: ``` Install-Package FluentMediator.Microsoft.Extensions.DependencyInjection ``` ## How Setup your events and pipelines using depedency injection. You can be very creative here! It supports async methods and cancellable tokens parameters, you could append multiple steps select one to return a message. An example: ```c# services.AddFluentMediator(builder => { builder.On().Pipeline() .Call((handler, request) => handler.MyMethod(request)) .Call((handler, request) => handler.MyLongMethod(request)) .Return( (handler, request) => handler.MyOtherMethod(request) ); }); ``` Then you are able to use the injected `IMediator` interface. ### Publishing Events ```c# // Puts the message in the pipeline, calls three handlers. mediator.Publish(ping); ``` ### Sending Commands and Queries ```c# // Calls the three handlers then get the response from `MyOtherMethod(PingRequest)`. PingResponse response = mediator.Send(new PingRequest("Ping")); Console.WriteLine(response.Message); // Prints "Pong" ``` ## Why When designing *CQRS* or *Event-Driven* applications we need to publish events from the infrastructure layer into the *domain event handlers*. We do not want framework dependencies leaking out to the Model then **FluentMediator** was born. ## Contributors
Ivan Paulovich
Ivan Paulovich

💻 🎨 ⚠️
Joakim Carselind
Joakim Carselind

👀 🤔
Vaggelis Mparmpas
Vaggelis Mparmpas

⚠️
Please contribute with [Issues](https://github.com/ivanpaulovich/FluentMediator/issues), [Wiki](https://github.com/ivanpaulovich/FluentMediator/wiki) and [Samples](https://github.com/ivanpaulovich/FluentMediator/tree/master/samples). ================================================ FILE: azure-pipelines-1.yml ================================================ # ASP.NET Core (.NET Framework) # Build and test ASP.NET Core projects targeting the full .NET Framework. # Add steps that publish symbols, save build artifacts, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core trigger: tags: include: - v* pool: vmImage: 'windows-latest' variables: solution: '**/*.sln' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: - task: NuGetToolInstaller@1 - task: NuGetCommand@2 inputs: restoreSolution: '$(solution)' - task: VSBuild@1 inputs: solution: '$(solution)' msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' - task: DotNetCoreCLI@2 inputs: command: 'test' projects: 'test/UnitTests/UnitTests.csproj' testRunTitle: 'Test' - task: DotNetCoreCLI@2 inputs: command: 'pack' packagesToPack: 'src/**/*.csproj' nobuild: true includesymbols: true includesource: true versioningScheme: 'off' - task: GitHubRelease@1 inputs: gitHubConnection: ivanpaulovich-github repositoryName: '$(Build.Repository.Name)' action: 'create' target: '$(Build.SourceVersion)' tagSource: 'gitTag' changeLogCompareToRelease: 'lastFullRelease' changeLogType: 'commitBased' - task: NuGetCommand@2 inputs: command: 'push' packagesToPush: '$(Build.ArtifactStagingDirectory)/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/**/*.symbols.nupkg' nuGetFeedType: 'external' publishFeedCredentials: 'NugetOrg' ================================================ FILE: azure-pipelines.yml ================================================ # ASP.NET Core (.NET Framework) # Build and test ASP.NET Core projects targeting the full .NET Framework. # Add steps that publish symbols, save build artifacts, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core trigger: - master pool: vmImage: 'windows-latest' variables: solution: '**/*.sln' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: - task: NuGetToolInstaller@1 - task: NuGetCommand@2 inputs: restoreSolution: '$(solution)' - task: VSBuild@1 inputs: solution: '$(solution)' msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' - task: DotNetCoreCLI@2 inputs: command: 'test' projects: 'test/UnitTests/UnitTests.csproj' testRunTitle: 'Test' ================================================ FILE: changelog.md ================================================ # Change Log ## 2020-02-04 - 0.4.7 - #48 Changed `PipelineNotFoundException` to internal. - #48 Removed sealed modified from Mediator to allow derived implementations. - #48 Added `OnPipelineNotFound` event to `IMediator` interface. - #48 Added `void OnPipelineNotFound(PipelineNotFoundEventArgs e)` handler to `Mediator` class. ## 2019-10-20 - 0.4.6 * #25 Cancellation Token fixed. * Added XML docs. ## 2019-10-20 - 0.4.5 * #37 Validation for Null Requests added. ## 2019-10-20 - 0.4.3 * #2 Support o Named Pipelines Added. ## 2019-10-20 - 0.4.0 * Refactoring. ## 2019-10-19 - 0.3.3 * #31 Support Scoped & Transient Lifetime. * Refactoring Tests. ## 2019-10-19 - 0.3.2 * Nuget Package Metadata added. ## 2019-10-13 - 0.3.1 * Implementation details made internal. ## 2019-10-13 - 0.3.0 * #32 Segregated Builder and Messaging interfaces. * #31 Support Scoped & Transient Lifetime. ## 2019-10-13 - 0.2.0 * #27 Added PipelineAlreadyExistsException. * #27 Added PipelineNotFoundException. ## 2019-10-13 - 0.1.0 * #24 Added ReturnFunctionIsNullException for misconfigured Pipelines. * SendAsync(request, ct) added to the public interfaces. * Refactoring. ================================================ FILE: samples/AspNetCore/.vscode/launch.json ================================================ { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (web)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceFolder}/src/WebApi/bin/Debug/netcoreapp3.0/WebApi.dll", "args": [], "cwd": "${workspaceFolder}/src/WebApi", "stopAtEntry": false, // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser "serverReadyAction": { "action": "openExternally", "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)" }, "env": { "ASPNETCORE_ENVIRONMENT": "Development" }, "sourceFileMap": { "/Views": "${workspaceFolder}/Views" } }, { "name": ".NET Core Attach", "type": "coreclr", "request": "attach", "processId": "${command:pickProcess}" } ] } ================================================ FILE: samples/AspNetCore/.vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "build", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/src/WebApi/WebApi.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "publish", "command": "dotnet", "type": "process", "args": [ "publish", "${workspaceFolder}/src/WebApi/WebApi.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "watch", "command": "dotnet", "type": "process", "args": [ "watch", "run", "${workspaceFolder}/src/WebApi/WebApi.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" } ] } ================================================ FILE: samples/AspNetCore/Wallet.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{E199B813-DCAA-4DED-A175-38BFE58E37C2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "src\Core\Core.csproj", "{8072924A-5C32-49C3-9314-40B1B274A572}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{93CE9A2D-B055-4E18-B7DE-C59441A02A84}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "src\WebApi\WebApi.csproj", "{E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8660B991-2482-4B36-BDBF-873136F571AD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "test\UnitTests\UnitTests.csproj", "{34641012-F6D1-46FD-95EC-BC03E79AC67F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|Any CPU.Build.0 = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|x64.ActiveCfg = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|x64.Build.0 = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|x86.ActiveCfg = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Debug|x86.Build.0 = Debug|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|Any CPU.ActiveCfg = Release|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|Any CPU.Build.0 = Release|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|x64.ActiveCfg = Release|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|x64.Build.0 = Release|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|x86.ActiveCfg = Release|Any CPU {8072924A-5C32-49C3-9314-40B1B274A572}.Release|x86.Build.0 = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|Any CPU.Build.0 = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|x64.ActiveCfg = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|x64.Build.0 = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|x86.ActiveCfg = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Debug|x86.Build.0 = Debug|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|Any CPU.ActiveCfg = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|Any CPU.Build.0 = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|x64.ActiveCfg = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|x64.Build.0 = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|x86.ActiveCfg = Release|Any CPU {93CE9A2D-B055-4E18-B7DE-C59441A02A84}.Release|x86.Build.0 = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|Any CPU.Build.0 = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|x64.ActiveCfg = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|x64.Build.0 = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|x86.ActiveCfg = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Debug|x86.Build.0 = Debug|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|Any CPU.ActiveCfg = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|Any CPU.Build.0 = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|x64.ActiveCfg = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|x64.Build.0 = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|x86.ActiveCfg = Release|Any CPU {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F}.Release|x86.Build.0 = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|Any CPU.Build.0 = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|x64.ActiveCfg = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|x64.Build.0 = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|x86.ActiveCfg = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Debug|x86.Build.0 = Debug|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|Any CPU.ActiveCfg = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|Any CPU.Build.0 = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|x64.ActiveCfg = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|x64.Build.0 = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|x86.ActiveCfg = Release|Any CPU {34641012-F6D1-46FD-95EC-BC03E79AC67F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8072924A-5C32-49C3-9314-40B1B274A572} = {E199B813-DCAA-4DED-A175-38BFE58E37C2} {93CE9A2D-B055-4E18-B7DE-C59441A02A84} = {E199B813-DCAA-4DED-A175-38BFE58E37C2} {E6077B21-BD4C-4F90-B6F8-3C2F88994A8F} = {E199B813-DCAA-4DED-A175-38BFE58E37C2} {34641012-F6D1-46FD-95EC-BC03E79AC67F} = {8660B991-2482-4B36-BDBF-873136F571AD} EndGlobalSection EndGlobal ================================================ FILE: samples/AspNetCore/src/Core/Core.csproj ================================================ netstandard2.1 enable true 8.0 true ================================================ FILE: samples/AspNetCore/src/Core/Services/ICustomerRepository.cs ================================================ using Core.Wallet; namespace Core.Services { public interface ICustomerRepository { void Add(Customer customer); } } ================================================ FILE: samples/AspNetCore/src/Core/UseCases/IRegisterUseCase.cs ================================================ namespace Core.UseCases { public interface IRegisterUseCase { RegisterResponse Execute(RegisterCommand registerCommand); } } ================================================ FILE: samples/AspNetCore/src/Core/UseCases/Register.cs ================================================ using Core.Services; using Core.Wallet; namespace Core.UseCases { public class Register : IRegisterUseCase { private readonly ICustomerRepository _customerRepository; public Register(ICustomerRepository customerRepository) { _customerRepository = customerRepository; } public RegisterResponse Execute(RegisterCommand registerCommand) { var customer = new Customer( registerCommand.Name, registerCommand.SSN, registerCommand.Balance ); _customerRepository.Add(customer); return new RegisterResponse(customer.Id); } } } ================================================ FILE: samples/AspNetCore/src/Core/UseCases/RegisterCommand.cs ================================================ namespace Core.UseCases { public class RegisterCommand { public string Name { get; private set; } public string SSN { get; private set; } public decimal Balance { get; private set; } public RegisterCommand(string name, string ssn, decimal balance) { Name = name; SSN = ssn; Balance = balance; } } } ================================================ FILE: samples/AspNetCore/src/Core/UseCases/RegisterResponse.cs ================================================ using System; namespace Core.UseCases { public class RegisterResponse { public Guid UserId { get; private set; } public RegisterResponse(Guid userId) { UserId = userId; } } } ================================================ FILE: samples/AspNetCore/src/Core/Wallet/Customer.cs ================================================ using System; namespace Core.Wallet { public class Customer { public Guid Id { get; protected set; } public string Name { get; protected set; } public string SSN { get; protected set; } public decimal Balance { get; protected set; } public DateTime Timestamp { get; protected set; } public Customer(string name, string ssn, decimal balance) { Id = Guid.NewGuid(); Name = name; SSN = ssn; Balance = balance; Timestamp = DateTime.Now; } } } ================================================ FILE: samples/AspNetCore/src/Infrastructure/InMemory/CustomerRepository.cs ================================================ using System.Collections.Generic; using Core.Services; using Core.Wallet; namespace Infrastructure.InMemory { public class CustomerRepository : ICustomerRepository { public IList Customers { get; } public CustomerRepository() { Customers = new List(); } public void Add(Customer customer) { Customers.Add(customer); } } } ================================================ FILE: samples/AspNetCore/src/Infrastructure/Infrastructure.csproj ================================================ netstandard2.1 enable true 8.0 true ================================================ FILE: samples/AspNetCore/src/WebApi/Controllers/Register/CustomersController.cs ================================================ using System.ComponentModel.DataAnnotations; using Core.UseCases; using FluentMediator; using Microsoft.AspNetCore.Mvc; namespace WebApi.Controllers.Register { [Route("api/[controller]")] [ApiController] public class CustomersController : ControllerBase { private readonly IMediator _mediator; public CustomersController(IMediator mediator) { _mediator = mediator; } [HttpPost] public IActionResult Post([FromBody][Required] RegisterRequest request) { var registerCommand = new RegisterCommand( request.Name, request.SSN, request.Balance ); var response = _mediator.Send(registerCommand); return Ok(response); } } } ================================================ FILE: samples/AspNetCore/src/WebApi/Controllers/Register/RegisterRequest.cs ================================================ namespace WebApi.Controllers.Register { public class RegisterRequest { public string Name { get; set; } public string SSN { get; set; } public decimal Balance { get; set; } } } ================================================ FILE: samples/AspNetCore/src/WebApi/Program.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace WebApi { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } ================================================ FILE: samples/AspNetCore/src/WebApi/Startup.cs ================================================ using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Core.Services; using Core.UseCases; using FluentMediator; using Infrastructure.InMemory; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace WebApi { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddTransient(); services.AddTransient(); services.AddFluentMediator(builder => { builder.On().Pipeline() .Return( (handler, request) => handler.Execute(request)); }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } } ================================================ FILE: samples/AspNetCore/src/WebApi/WebApi.csproj ================================================ netcoreapp3.0 InProcess ================================================ FILE: samples/AspNetCore/src/WebApi/appsettings.Development.json ================================================ { "Logging": { "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } } ================================================ FILE: samples/AspNetCore/src/WebApi/appsettings.json ================================================ { "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" } ================================================ FILE: samples/AspNetCore/test/UnitTests/UnitTests.csproj ================================================ netcoreapp3.0 false enable true 8.0 true ================================================ FILE: samples/AspNetCore/test/UnitTests/UseCasesTests/RegisterTests.cs ================================================ using Core.UseCases; using Infrastructure.InMemory; using Xunit; namespace UnitTests.UseCasesTests { public class RegisterTests { [Fact] public void Register_PublishesEvent() { // Arrange var customerRepository = new CustomerRepository(); var sut = new Register(customerRepository); var registerCommand = new RegisterCommand( "Ivan Paulovich", "198608175555", 460 ); // Act var response = sut.Execute(registerCommand); // Assert Assert.NotEmpty(customerRepository.Customers); } } } ================================================ FILE: samples/SimpleConsoleApp/.vscode/launch.json ================================================ { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md "version": "0.2.0", "configurations": [ { "name": ".NET Core Launch (console)", "type": "coreclr", "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceFolder}/PingPong/bin/Debug/netcoreapp3.0/PingPong.dll", "args": [], "cwd": "${workspaceFolder}/PingPong", // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console": "internalConsole", "stopAtEntry": false }, { "name": ".NET Core Attach", "type": "coreclr", "request": "attach", "processId": "${command:pickProcess}" } ] } ================================================ FILE: samples/SimpleConsoleApp/.vscode/settings.json ================================================ { "workbench.colorCustomizations": { "activityBar.background": "#1f6fd0", "activityBar.foreground": "#e7e7e7", "activityBar.inactiveForeground": "#e7e7e799", "activityBarBadge.background": "#ee90bb", "activityBarBadge.foreground": "#15202b", "titleBar.activeBackground": "#1857a4", "titleBar.inactiveBackground": "#1857a499", "titleBar.activeForeground": "#e7e7e7", "titleBar.inactiveForeground": "#e7e7e799", "statusBar.background": "#1857a4", "statusBarItem.hoverBackground": "#1f6fd0", "statusBar.foreground": "#e7e7e7" }, "peacock.color": "#1857a4" } ================================================ FILE: samples/SimpleConsoleApp/.vscode/tasks.json ================================================ { "version": "2.0.0", "tasks": [ { "label": "build", "command": "dotnet", "type": "process", "args": [ "build", "${workspaceFolder}/PingPong/PingPong.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "publish", "command": "dotnet", "type": "process", "args": [ "publish", "${workspaceFolder}/PingPong/PingPong.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" }, { "label": "watch", "command": "dotnet", "type": "process", "args": [ "watch", "run", "${workspaceFolder}/PingPong/PingPong.csproj", "/property:GenerateFullPaths=true", "/consoleloggerparameters:NoSummary" ], "problemMatcher": "$msCompile" } ] } ================================================ FILE: samples/SimpleConsoleApp/PingPong/PingHandler.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; namespace PingPong { public class PingHandler { public void MyMethod(PingRequest request) { Console.WriteLine($"{ request.Message } .. Pong "); } public void MyLongMethod(PingRequest request) { Console.WriteLine($"{ request.Message } ............... Pong"); } public async Task MyMethodAsync(PingRequest request) { Console.WriteLine($"{ request.Message } > > > > Pong "); await Task.CompletedTask; } public async Task MyMethodAsync(PingRequest request, CancellationToken cancelationToken) { Console.WriteLine($"{ request.Message } - - - - - Pong "); await Task.CompletedTask; } } } ================================================ FILE: samples/SimpleConsoleApp/PingPong/PingPong.csproj ================================================ Exe netcoreapp2.2 ================================================ FILE: samples/SimpleConsoleApp/PingPong/PingRequest.cs ================================================ namespace PingPong { public class PingRequest { public string Message { get; } public PingRequest(string message) { Message = message; } } } ================================================ FILE: samples/SimpleConsoleApp/PingPong/Program.cs ================================================ using System; using System.Threading; using FluentMediator; using Microsoft.Extensions.DependencyInjection; namespace PingPong { class Program { static void Main(string[] args) { var serviceCollection = new ServiceCollection(); serviceCollection.AddFluentMediator(builder => { builder.On().Pipeline() .Call((handler, req) => handler.MyMethod(req)) .Call((handler, req) => handler.MyLongMethod(req)); builder.On().PipelineAsync() .Call(async(handler, req) => await handler.MyMethodAsync(req)); builder.On().CancellablePipelineAsync() .Call(async(handler, req, ct) => await handler.MyMethodAsync(req, ct)); }); serviceCollection.AddScoped(); var provider = serviceCollection.BuildServiceProvider(); var mediator = provider.GetService(); var ping = new PingRequest("Ping"); var cts = new CancellationTokenSource(); Console.WriteLine("Publishing Ping. Should Pong Twice."); mediator.Publish(ping); Console.WriteLine("Publishing Ping Async. Should Pong One."); mediator.PublishAsync(ping) .GetAwaiter() .GetResult(); Console.WriteLine("Publishing Cancellable Ping. Should Pong One."); mediator.PublishAsync(ping, cts.Token) .GetAwaiter() .GetResult(); Console.ReadLine(); } } } ================================================ FILE: samples/SimpleConsoleApp/Samples.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PingPong", "PingPong\PingPong.csproj", "{F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|x64.ActiveCfg = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|x64.Build.0 = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|x86.ActiveCfg = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Debug|x86.Build.0 = Debug|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|Any CPU.Build.0 = Release|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|x64.ActiveCfg = Release|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|x64.Build.0 = Release|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|x86.ActiveCfg = Release|Any CPU {F3A8DBEF-1CE1-4456-9B65-5A37A57B3A4E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal ================================================ FILE: src/FluentMediator/FluentMediator.csproj ================================================ netstandard1.1 enable true 8.0 true bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml FluentMediator 0.4.7 Ivan Paulovich Ivan Paulovich FluentMediator is an unobtrusive library that allows developers to build custom pipelines for Commands, Queries and Events. FluentMediator is an unobtrusive library that allows developers to build custom pipelines for Commands, Queries and Events. fluent-design;mediator-pattern;ddd-cqrs;message-bus;event-sourcing;event-driven;chain-of-responsibility;chain-methods;pipelines;dotnet-core;craftmanship;tdd;csharp;pipeline-framework;fluent-interface;event-handlers true icon.png https://github.com/ivanpaulovich/FluentMediator en-US true true snupkg True ================================================ FILE: src/FluentMediator/GetService.cs ================================================ using System; namespace FluentMediator { /// /// Retrieves a Handler Service from the Container /// /// /// public delegate object GetService(Type serviceType); } ================================================ FILE: src/FluentMediator/IMediator.cs ================================================ using System; using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator { /// /// Publishes/Sends messages through the Pipelines /// public interface IMediator: ISyncMediator, IAsyncMediator, ICancellableMediator { /// /// On Pipeline Not Found Event Handler. /// event EventHandler ? PipelineNotFound; } } ================================================ FILE: src/FluentMediator/IPipelineProvider.cs ================================================ using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator { /// /// Retrieves a Pipeline for a specific Message /// public interface IPipelineProvider: ISyncPipelineProvider, IAsyncPipelineProvider, ICancellablePipelineProvider { } } ================================================ FILE: src/FluentMediator/IPipelineProviderBuilder.cs ================================================ using FluentMediator.Pipelines; using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator { /// /// Builds pipelines for a specific message /// public interface IPipelineProviderBuilder: ISyncPipelineProviderBuilder, IAsyncPipelineProviderBuilder, ICancellablePipelineProviderBuilder { /// /// Begin building a pipeline for a specific message /// /// Message Type /// A more specific PipelineBehavior IPipelineBehavior On(); /// /// Builds the pipeline /// /// An immutable Pipeline Provider IPipelineProvider Build(); } } ================================================ FILE: src/FluentMediator/Mediator.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; using FluentMediator.Pipelines; namespace FluentMediator { /// /// Publishes/Sends messages through the Pipelines /// public class Mediator : IMediator { /// /// Returns a service from the Container /// /// public GetService GetService { get; } private IPipelineProvider _pipelines; /// /// On Pipeline Not Found Handler. /// public event EventHandler ? PipelineNotFound; /// /// Instantiate a Mediator /// /// Service Provider /// Pipeline Provider public Mediator( GetService getService, IPipelineProvider pipelines) { GetService = getService; _pipelines = pipelines; } /// /// Publishes messages through the Pipeline /// /// Message /// An optional pipeline name public void Publish(object request, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } try { if (pipelineName is string) { var pipeline = _pipelines.GetPipeline(pipelineName); pipeline.Publish(GetService, request!); } else { var pipeline = _pipelines.GetPipeline(request.GetType()); pipeline.Publish(GetService, request!); } } catch (PipelineNotFoundException) { var e = new PipelineNotFoundEventArgs(request); OnPipelineNotFound(e); } } /// /// Publishes messages through the Pipeline /// /// Message /// An optional pipeline name /// The desired Typed result /// The result object public TResult Send(object request, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } if (pipelineName is string) { var pipeline = _pipelines.GetPipeline(pipelineName); return pipeline.Send(GetService, request); } else { var pipeline = _pipelines.GetPipeline(request.GetType()); return pipeline.Send(GetService, request); } } /// /// Publishes messages through the Pipeline /// /// Message /// An optional pipeline name /// Task object public async Task PublishAsync(object request, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } if (pipelineName is string) { var pipeline = _pipelines.GetAsyncPipeline(pipelineName); await pipeline.PublishAsync(GetService, request); } else { var pipeline = _pipelines.GetAsyncPipeline(request.GetType()); await pipeline.PublishAsync(GetService, request); } } /// /// Publishes messages through the Pipeline /// /// Message /// An optional pipeline name /// The desired Typed result /// The result object public async Task SendAsync(object request, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } if (pipelineName is string) { var pipeline = _pipelines.GetAsyncPipeline(pipelineName); return await pipeline.SendAsync(GetService, request); } else { var pipeline = _pipelines.GetAsyncPipeline(request.GetType()); return await pipeline.SendAsync(GetService, request); } } /// /// Publishes messages through the Pipeline /// /// Message /// Cancellation Token to gracefully exit in middle of execution /// Optional Pipeline Name /// Task object public async Task PublishAsync(object request, CancellationToken cancellationToken, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } if (pipelineName is string) { var pipeline = _pipelines.GetCancellablePipeline(pipelineName); await pipeline.PublishAsync(GetService, request, cancellationToken); } else { var pipeline = _pipelines.GetCancellablePipeline(request.GetType()); await pipeline.PublishAsync(GetService, request, cancellationToken); } } /// /// Sends messages through the Pipeline /// /// Message /// Cancellation Token to gracefully exit in middle of execution /// Optional Pipeline Name /// Result Type /// Result object public async Task SendAsync(object request, CancellationToken cancellationToken, string? pipelineName = null) { if (request is null) { throw new NullRequestException("The request is null."); } if (pipelineName is string) { var pipeline = _pipelines.GetCancellablePipeline(pipelineName); return await pipeline.SendAsync(GetService, request, cancellationToken); } else { var pipeline = _pipelines.GetCancellablePipeline(request.GetType()); return await pipeline.SendAsync(GetService, request, cancellationToken); } } /// /// On Pipeline Not Found. /// /// OnErrorEventArgs. protected virtual void OnPipelineNotFound(PipelineNotFoundEventArgs e) { if (this.PipelineNotFound is EventHandler) { this.PipelineNotFound(this, e); } } } } ================================================ FILE: src/FluentMediator/MediatorException.cs ================================================ using System; namespace FluentMediator { /// /// All Exceptions from FluentMediator are derived from MediatorException /// public class MediatorException : Exception { /// /// Instantiate a MediatorException /// /// Error message /// The exception public MediatorException(string message) : base(message) { } } } ================================================ FILE: src/FluentMediator/NullRequestException.cs ================================================ namespace FluentMediator { /// /// Occurs when the message is null /// public class NullRequestException : MediatorException { /// /// Instantiate an Exception /// /// The message /// An Exception instance public NullRequestException(string message) : base(message) { } } } ================================================ FILE: src/FluentMediator/PipelineNotFoundEventArgs.cs ================================================ using System; namespace FluentMediator { /// /// On Error Event. /// public class PipelineNotFoundEventArgs : EventArgs { /// /// /// /// public object Message { get; } /// /// /// /// public PipelineNotFoundEventArgs(object message) { this.Message = message; } } } ================================================ FILE: src/FluentMediator/PipelineProvider.cs ================================================ using System; using FluentMediator.Pipelines; using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator { /// /// Retrieves Pipelines for a message /// internal sealed class PipelineProvider : IPipelineProvider { private readonly IPipelineCollection _pipelineCollection; private readonly IPipelineCollection _asyncPipelineCollection; private readonly IPipelineCollection _cancellablePipelineCollection; /// /// Instantiate a PipelineProvider /// /// Sync Pipelines /// Async Pipelines /// Cancellable Pipelines public PipelineProvider( IPipelineCollection pipelineCollection, IPipelineCollection asyncPipelineCollection, IPipelineCollection cancellablePipelineCollection) { _pipelineCollection = pipelineCollection; _asyncPipelineCollection = asyncPipelineCollection; _cancellablePipelineCollection = cancellablePipelineCollection; } /// /// Gets an async pipeline /// /// Message Type /// Pipeline public IPipelineAsync GetAsyncPipeline(Type requestType) { return _asyncPipelineCollection.Get(requestType); } /// /// Gets an async pipeline /// /// Pipeline Name /// Pipeline public IPipelineAsync GetAsyncPipeline(string pipelineName) { return _asyncPipelineCollection.Get(pipelineName); } /// /// Gets a cancellable pipeline /// /// Request Type /// Pipeline public ICancellablePipelineAsync GetCancellablePipeline(Type requestType) { return _cancellablePipelineCollection.Get(requestType); } /// /// Gets a cancellable pipeline /// /// Pipeline Name /// Pipeline public ICancellablePipelineAsync GetCancellablePipeline(string pipelineName) { return _cancellablePipelineCollection.Get(pipelineName); } /// /// Gets a Pipeline /// /// Request Type /// Pipeline public IPipeline GetPipeline(Type requestType) { return _pipelineCollection.Get(requestType); } /// /// Gets a Pipeline /// /// Pipeline Name /// Pipeline public IPipeline GetPipeline(string pipelineName) { return _pipelineCollection.Get(pipelineName); } } } ================================================ FILE: src/FluentMediator/PipelineProviderBuilder.cs ================================================ using System.Collections.Generic; using System.Collections.ObjectModel; using FluentMediator.Pipelines; using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator { /// /// PipelineProvider Builder /// public class PipelineProviderBuilder : IPipelineProviderBuilder { private ICollection _pipelineBuilderCollection { get; } private ICollection _asyncPipelineBuilderCollection { get; } private ICollection _cancellablePipelineBuilderCollection { get; } /// /// Instantiate a PipelineProviderBuilder /// public PipelineProviderBuilder() { _pipelineBuilderCollection = new Collection(); _asyncPipelineBuilderCollection = new Collection(); _cancellablePipelineBuilderCollection = new Collection(); } /// /// Returns a PipelineBehavior for a Message Type /// /// MessageType /// PipelineBehavior public IPipelineBehavior On() { var behavior = new PipelineBehavior(this); return behavior; } /// /// Adds a Pipeline /// /// PipelineBuilder /// PipelineBuilder public IPipelineBuilder Add(IPipelineBuilder pipelineBuilder) { _pipelineBuilderCollection.Add(pipelineBuilder); return pipelineBuilder; } /// /// Adds a Pipeline /// /// PipelineBuilder /// PipelineBuilder public IPipelineAsyncBuilder Add(IPipelineAsyncBuilder pipelineBuilder) { _asyncPipelineBuilderCollection.Add(pipelineBuilder); return pipelineBuilder; } /// /// Adds a Pipeline /// /// PipelineBuilder /// PipelineBuilder public ICancellablePipelineAsyncBuilder Add(ICancellablePipelineAsyncBuilder pipelineBuilder) { _cancellablePipelineBuilderCollection.Add(pipelineBuilder); return pipelineBuilder; } /// /// Builds a PipelineProvider /// /// Returns a immutable PipelineProvider public IPipelineProvider Build() { var pipelineCollection = new PipelineCollection(); var asyncPipelineCollection = new PipelineCollection(); var cancellablePipelineCollection = new PipelineCollection(); foreach (var item in _pipelineBuilderCollection) { var pipeline = item.Build(); pipelineCollection.Add(pipeline); } foreach (var item in _asyncPipelineBuilderCollection) { var pipeline = item.Build(); asyncPipelineCollection.Add(pipeline); } foreach (var item in _cancellablePipelineBuilderCollection) { var pipeline = item.Build(); cancellablePipelineCollection.Add(pipeline); } return new PipelineProvider( pipelineCollection, asyncPipelineCollection, cancellablePipelineCollection ); } } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/Direct.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { internal sealed class Direct : IDirect { private readonly Method>> _method; public Direct(Func> action) { Func> typedHandler = (h, req, ct) => action((THandler) h, (TRequest) req, ct); _method = new Method>>(typeof(THandler), typedHandler); } public async Task SendAsync(GetService getService, object request, CancellationToken cancellationToken) { var concreteHandler = getService(typeof(THandler)); Func> typedHandler = (h, req, ct) => (Task) (object) _method.Action((THandler) concreteHandler, (TRequest) (object) request!, ct); return await typedHandler((THandler) concreteHandler, (TRequest) (object) request!, cancellationToken); } } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/ICancellableMediator.cs ================================================ using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { /// /// Cancellable Mediator /// public interface ICancellableMediator { /// /// Publishes a message /// /// A message /// Cancellation Token /// Pipeline Name /// Task object Task PublishAsync(object request, CancellationToken cancellationToken, string? pipelineName = null); /// /// Sends a message /// /// A message /// Cancellation Token /// Pipeline Name /// Result Type /// Task SendAsync(object request, CancellationToken cancellationToken, string? pipelineName = null); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/ICancellablePipelineAsync.cs ================================================ using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { /// /// Cancellable Pipeline /// public interface ICancellablePipelineAsync : INamedPipeline, ITypedPipeline { /// /// Publishes a message /// /// Retriever a service from the container /// Request message /// Cancellation Token /// Task object Task PublishAsync(GetService getService, object request, CancellationToken cancellationToken); /// /// Sends a message /// /// Retriever a service from the container /// Request message /// Cancellation Token /// Message type /// Response message Task SendAsync(GetService getService, object request, CancellationToken cancellationToken); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/ICancellablePipelineAsyncBuilder.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { /// /// Cancellable Pipeline /// /// public interface ICancellablePipelineAsyncBuilder : ICancellablePipelineAsyncBuilder { /// /// /// /// /// /// ICancellablePipelineAsyncBuilder Call(Func func); /// /// /// /// /// /// /// ICancellablePipelineAsync Return(Func> func); } /// /// /// public interface ICancellablePipelineAsyncBuilder { /// /// /// /// ICancellablePipelineAsync Build(); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/ICancellablePipelineProvider.cs ================================================ using System; namespace FluentMediator.Pipelines.CancellablePipelineAsync { /// /// /// public interface ICancellablePipelineProvider { /// /// /// /// /// ICancellablePipelineAsync GetCancellablePipeline(Type requestType); /// /// /// /// /// ICancellablePipelineAsync GetCancellablePipeline(string pipelineName); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/ICancellablePipelineProviderBuilder.cs ================================================ namespace FluentMediator.Pipelines.CancellablePipelineAsync { /// /// /// public interface ICancellablePipelineProviderBuilder { /// /// /// /// /// ICancellablePipelineAsyncBuilder Add(ICancellablePipelineAsyncBuilder pipelineBuilder); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/IDirect.cs ================================================ using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { internal interface IDirect { Task SendAsync( GetService getService, object request, CancellationToken cancellationToken ); } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/Pipeline.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { internal sealed class Pipeline : ICancellablePipelineAsync { private readonly IMethodCollection>> _methods; private readonly IDirect? _direct; public Pipeline(IMethodCollection>> methods, IDirect? direct, Type requestType, string? name) { _methods = methods; _direct = direct; RequestType = requestType; Name = name; } public Type RequestType { get; } public string? Name { get; } public async Task PublishAsync(GetService getService, object request, CancellationToken cancellationToken) { foreach (var handler in _methods.GetMethods()) { cancellationToken.ThrowIfCancellationRequested(); var concreteHandler = getService(handler.HandlerType); await handler.Action(concreteHandler, request, cancellationToken); } } public async Task SendAsync(GetService getService, object request, CancellationToken cancellationToken) { if (_direct is null) { throw new ReturnFunctionIsNullException("The return function is null. SendAsync method not executed."); } foreach (var handler in _methods.GetMethods()) { cancellationToken.ThrowIfCancellationRequested(); var concreteHandler = getService(handler.HandlerType); await handler.Action(concreteHandler, request, cancellationToken); } cancellationToken.ThrowIfCancellationRequested(); return await _direct.SendAsync(getService, request!, cancellationToken) !; } } } ================================================ FILE: src/FluentMediator/Pipelines/CancellablePipelineAsync/PipelineBuilder.cs ================================================ using System; using System.Threading; using System.Threading.Tasks; namespace FluentMediator.Pipelines.CancellablePipelineAsync { internal class PipelineBuilder : ICancellablePipelineAsyncBuilder { private readonly IMethodCollection>> _methods; private IDirect? _direct; private string? _name; public PipelineBuilder(string? name) { _methods = new MethodCollection>>(); _name = name; } public ICancellablePipelineAsyncBuilder Call(Func func) { Func typedHandler = async(h, r, c) => await func((THandler) h, (TRequest) r, c); var method = new Method>(typeof(THandler), typedHandler); _methods.Add(method); return this; } public ICancellablePipelineAsync Return(Func> func) { _direct = new Direct(func); return Build(); } public ICancellablePipelineAsync Build() { return new Pipeline(_methods, _direct, typeof(TRequest), _name); } } } ================================================ FILE: src/FluentMediator/Pipelines/IMethodCollection.cs ================================================ using System.Collections.ObjectModel; namespace FluentMediator.Pipelines { internal interface IMethodCollection { ReadOnlyCollection GetMethods(); void Add(Method method); } } ================================================ FILE: src/FluentMediator/Pipelines/INamedPipeline.cs ================================================ namespace FluentMediator.Pipelines { /// /// Named Pipeline /// public interface INamedPipeline { /// /// An unique pipeline name /// /// null string? Name { get; } } } ================================================ FILE: src/FluentMediator/Pipelines/IPipelineBehavior.cs ================================================ using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator.Pipelines { /// /// PipelineBehavior /// /// public interface IPipelineBehavior { /// /// Creates a IPipelineBuilder /// /// An unique name or null /// IPipelineBuilder IPipelineBuilder Pipeline(string? pipelineName = null); /// /// Creates an IPipelineAsyncBuilder /// /// An unique name or null /// IPipelineAsyncBuilder IPipelineAsyncBuilder PipelineAsync(string? pipelineName = null); /// /// Creates an ICancellablePipelineAsyncBuilder /// /// An unique name or null /// ICancellablePipelineAsyncBuilder ICancellablePipelineAsyncBuilder CancellablePipelineAsync(string? pipelineName = null); } } ================================================ FILE: src/FluentMediator/Pipelines/IPipelineCollection.cs ================================================ using System; namespace FluentMediator.Pipelines { internal interface IPipelineCollection where TPipeline : class, ITypedPipeline { void Add(TPipeline pipeline); TPipeline Get(Type requestType); TPipeline Get(string pipelineName); } } ================================================ FILE: src/FluentMediator/Pipelines/ITypedPipeline.cs ================================================ using System; namespace FluentMediator.Pipelines { /// /// A Typed Pipeline /// public interface ITypedPipeline { /// /// A RequestType /// /// Type RequestType { get; } } } ================================================ FILE: src/FluentMediator/Pipelines/Method.cs ================================================ using System; namespace FluentMediator.Pipelines { internal sealed class Method { public Type HandlerType { get; } public TAction Action { get; } public Method(Type handlerType, TAction action) { HandlerType = handlerType; Action = action; } } } ================================================ FILE: src/FluentMediator/Pipelines/MethodCollection.cs ================================================ using System.Collections.Generic; using System.Collections.ObjectModel; namespace FluentMediator.Pipelines { internal sealed class MethodCollection : IMethodCollection { private readonly IList _asyncMethods; public MethodCollection() { _asyncMethods = new List(); } public ReadOnlyCollection GetMethods() { return new ReadOnlyCollection(_asyncMethods); } public void Add(Method method) { _asyncMethods.Add(method); } } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/Direct.cs ================================================ using System; namespace FluentMediator.Pipelines.Pipeline { internal sealed class Direct : IDirect { private readonly Method> _method; public Direct(Func action) { Func typedHandler = (h, req) => action((THandler) h, (TRequest) req); _method = new Method>(typeof(THandler), typedHandler); } public TResponse Send(GetService getService, object request) { var concreteHandler = getService(_method.HandlerType); return (TResponse) (object) _method.Action((THandler) concreteHandler, (TRequest) request) !; } } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/IDirect.cs ================================================ namespace FluentMediator.Pipelines.Pipeline { internal interface IDirect { TResult Send( GetService getService, object request ); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/IPipeline.cs ================================================ namespace FluentMediator.Pipelines.Pipeline { /// /// /// public interface IPipeline : INamedPipeline, ITypedPipeline { /// /// /// /// /// void Publish(GetService getService, object request); /// /// /// /// /// /// /// TResult Send(GetService getService, object request); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/IPipelineBuilder.cs ================================================ using System; namespace FluentMediator.Pipelines.Pipeline { /// /// /// /// public interface IPipelineBuilder : IPipelineBuilder { /// /// /// /// /// /// IPipelineBuilder Call(Action action); /// /// /// /// /// /// /// IPipeline Return(Func func); } /// /// /// public interface IPipelineBuilder { /// /// /// /// IPipeline Build(); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/ISyncMediator.cs ================================================ namespace FluentMediator.Pipelines.Pipeline { /// /// /// public interface ISyncMediator { /// /// /// /// /// void Publish(object request, string? pipelineName = null); /// /// /// /// /// /// /// TResult Send(object request, string? pipelineName = null); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/ISyncPipelineProvider.cs ================================================ using System; namespace FluentMediator.Pipelines.Pipeline { /// /// /// public interface ISyncPipelineProvider { /// /// /// /// /// IPipeline GetPipeline(Type requestType); /// /// /// /// /// IPipeline GetPipeline(string pipelineName); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/ISyncPipelineProviderBuilder.cs ================================================ namespace FluentMediator.Pipelines.Pipeline { /// /// /// public interface ISyncPipelineProviderBuilder { /// /// /// /// /// IPipelineBuilder Add(IPipelineBuilder pipelineBuilder); } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/Pipeline.cs ================================================ using System; namespace FluentMediator.Pipelines.Pipeline { internal sealed class Pipeline : IPipeline { private readonly IMethodCollection>> _methods; private readonly IDirect? _direct; public Pipeline(IMethodCollection>> methods, IDirect? direct, Type requestType, string? name) { _methods = methods; _direct = direct; RequestType = requestType; Name = name; } public Type RequestType { get; } public string? Name { get; } public void Publish(GetService getService, object request) { foreach (var handler in _methods.GetMethods()) { var concreteHandler = getService(handler.HandlerType); handler.Action(concreteHandler, request); } } public TResult Send(GetService getService, object request) { if (_direct is null) { throw new ReturnFunctionIsNullException("The return function is null. Send method not executed."); } foreach (var handler in _methods.GetMethods()) { var concreteHandler = getService(handler.HandlerType); handler.Action(concreteHandler, request); } return _direct.Send(getService, request!) !; } } } ================================================ FILE: src/FluentMediator/Pipelines/Pipeline/PipelineBuilder.cs ================================================ using System; namespace FluentMediator.Pipelines.Pipeline { internal sealed class PipelineBuilder : IPipelineBuilder { private readonly IMethodCollection>> _methods; private IDirect? _direct; private string? _name; public PipelineBuilder(string? name) { _methods = new MethodCollection>>(); _name = name; } public IPipelineBuilder Call(Action action) { Action typedHandler = (h, r) => action((THandler) h, (TRequest) r); var method = new Method>(typeof(THandler), typedHandler); _methods.Add(method); return this; } public IPipeline Return(Func func) { _direct = new Direct(func); return Build(); } public IPipeline Build() { return new Pipeline(_methods, _direct, typeof(TRequest), _name); } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAlreadyExistsException.cs ================================================ namespace FluentMediator.Pipelines { /// /// Occurs when pipelines have the same name /// public sealed class PipelineAlreadyExistsException : MediatorException { /// /// Instantiate an PipelineAlreadyExistsException /// /// Message /// PipelineAlreadyExistsException public PipelineAlreadyExistsException(string message) : base(message) { } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/Direct.cs ================================================ using System; using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { internal sealed class Direct : IDirect { private readonly Method>> _method; public Direct(Func> action) { Func> typedHandler = (h, req) => action((THandler) h, (TRequest) req); _method = new Method>>(typeof(THandler), typedHandler); } public async Task SendAsync(GetService getService, object request) { var concreteHandler = getService(typeof(THandler)); Func> typedHandler = (h, req) => (Task) (object) _method.Action((THandler) concreteHandler, (TRequest) (object) request!); return await typedHandler((THandler) concreteHandler, (TRequest) (object) request!); } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IAsyncMediator.cs ================================================ using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { /// /// /// public interface IAsyncMediator { /// /// /// /// /// /// Task PublishAsync(object request, string? pipelineName = null); /// /// /// /// /// /// /// Task SendAsync(object request, string? pipelineName = null); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IAsyncPipelineProvider.cs ================================================ using System; namespace FluentMediator.Pipelines.PipelineAsync { /// /// /// public interface IAsyncPipelineProvider { /// /// /// /// /// IPipelineAsync GetAsyncPipeline(Type requestType); /// /// /// /// /// IPipelineAsync GetAsyncPipeline(string pipelineName); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IAsyncPipelineProviderBuilder.cs ================================================ namespace FluentMediator.Pipelines.PipelineAsync { /// /// /// public interface IAsyncPipelineProviderBuilder { /// /// /// /// /// IPipelineAsyncBuilder Add(IPipelineAsyncBuilder pipelineBuilder); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IDirect.cs ================================================ using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { internal interface IDirect { Task SendAsync( GetService getService, object request ); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IPipelineAsync.cs ================================================ using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { /// /// /// public interface IPipelineAsync : INamedPipeline, ITypedPipeline { /// /// /// /// /// /// Task PublishAsync(GetService getService, object request); /// /// /// /// /// /// /// Task SendAsync(GetService getService, object request); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/IPipelineAsyncBuilder.cs ================================================ using System; using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { /// /// /// /// public interface IPipelineAsyncBuilder : IPipelineAsyncBuilder { /// /// /// /// /// /// IPipelineAsyncBuilder Call(Func func); /// /// /// /// /// /// /// IPipelineAsync Return(Func> func); } /// /// /// public interface IPipelineAsyncBuilder { /// /// /// /// IPipelineAsync Build(); } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/Pipeline.cs ================================================ using System; using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { internal sealed class Pipeline : IPipelineAsync { private readonly IMethodCollection>> _methods; private readonly IDirect? _direct; public Pipeline(IMethodCollection>> methods, IDirect? direct, Type requestType, string? name) { _methods = methods; _direct = direct; RequestType = requestType; Name = name; } public Type RequestType { get; } public string? Name { get; } public async Task PublishAsync(GetService getService, object request) { foreach (var handler in _methods.GetMethods()) { var concreteHandler = getService(handler.HandlerType); await handler.Action(concreteHandler, request); } } public async Task SendAsync(GetService getService, object request) { if (_direct is null) { throw new ReturnFunctionIsNullException("The return function is null. SendAsync method not executed."); } foreach (var handler in _methods.GetMethods()) { var concreteHandler = getService(handler.HandlerType); await handler.Action(concreteHandler, request); } return await _direct.SendAsync(getService, request!) !; } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineAsync/PipelineBuilder.cs ================================================ using System; using System.Threading.Tasks; namespace FluentMediator.Pipelines.PipelineAsync { internal sealed class PipelineBuilder : IPipelineAsyncBuilder { private readonly IMethodCollection>> _methods; private IDirect? _direct; private string? _name; public PipelineBuilder(string? name) { _methods = new MethodCollection>>(); _name = name; } public IPipelineAsyncBuilder Call(Func func) { Func typedHandler = async(h, r) => await func((THandler) h, (TRequest) r); var method = new Method>(typeof(THandler), typedHandler); _methods.Add(method); return this; } public IPipelineAsync Return(Func> func) { _direct = new Direct(func); return Build(); } public IPipelineAsync Build() { return new Pipeline(_methods, _direct, typeof(TRequest), _name); } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineBehavior.cs ================================================ using FluentMediator.Pipelines.CancellablePipelineAsync; using FluentMediator.Pipelines.Pipeline; using FluentMediator.Pipelines.PipelineAsync; namespace FluentMediator.Pipelines { internal sealed class PipelineBehavior : IPipelineBehavior { private readonly IPipelineProviderBuilder _pipelineProviderBuilder; public PipelineBehavior(IPipelineProviderBuilder pipelineProviderBuilder) { _pipelineProviderBuilder = pipelineProviderBuilder; } public IPipelineBuilder Pipeline(string? pipelineName = null) { var pipelineBuilder = new Pipeline.PipelineBuilder(pipelineName); _pipelineProviderBuilder.Add(pipelineBuilder); return pipelineBuilder; } public IPipelineAsyncBuilder PipelineAsync(string? pipelineName = null) { var pipelineBuilder = new PipelineAsync.PipelineBuilder(pipelineName); _pipelineProviderBuilder.Add(pipelineBuilder); return pipelineBuilder; } public ICancellablePipelineAsyncBuilder CancellablePipelineAsync(string? pipelineName = null) { var pipelineBuilder = new CancellablePipelineAsync.PipelineBuilder(pipelineName); _pipelineProviderBuilder.Add(pipelineBuilder); return pipelineBuilder; } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineCollection.cs ================================================ using System; using System.Collections.Generic; namespace FluentMediator.Pipelines { internal sealed class PipelineCollection : IPipelineCollection where TPipeline : class, ITypedPipeline, INamedPipeline { private readonly IDictionary _typedPipelines; private readonly IDictionary _namedPipelines; public PipelineCollection() { _typedPipelines = new Dictionary(); _namedPipelines = new Dictionary(); } public void Add(TPipeline pipeline) { if (pipeline.Name is string) { _namedPipelines.Add(pipeline.Name, pipeline); } else { if (_typedPipelines.ContainsKey(pipeline.RequestType)) { throw new PipelineAlreadyExistsException($"A pipeline for `{ pipeline.RequestType }` already exists."); } _typedPipelines.Add(pipeline.RequestType, pipeline); } } public TPipeline Get(Type requestType) { if (_typedPipelines.TryGetValue(requestType, out var pipeline)) { return pipeline; } throw new PipelineNotFoundException($"There is no pipeline configured for `{ requestType.GetType() }`."); } public TPipeline Get(string pipelineName) { if (_namedPipelines.TryGetValue(pipelineName, out var pipeline)) { return pipeline; } throw new PipelineNotFoundException($"There is no pipeline configured for `{ pipelineName }`."); } } } ================================================ FILE: src/FluentMediator/Pipelines/PipelineNotFoundException.cs ================================================ namespace FluentMediator.Pipelines { /// /// Occurs when a pipeline for a message was not found /// internal sealed class PipelineNotFoundException : MediatorException { /// /// Instantiate a PipelineNotFoundException /// /// The message /// PipelineNotFoundException public PipelineNotFoundException(string message) : base(message) { } } } ================================================ FILE: src/FluentMediator/Pipelines/ReturnFunctionIsNullException.cs ================================================ namespace FluentMediator.Pipelines { /// /// Occurs when a return function was not defined /// public sealed class ReturnFunctionIsNullException : MediatorException { /// /// Instantiate the Exception /// /// Exception Message /// An exception public ReturnFunctionIsNullException(string message) : base(message) { } } } ================================================ FILE: src/FluentMediator.Microsoft.Extensions.DependencyInjection/FluentMediator.Microsoft.Extensions.DependencyInjection.csproj ================================================ netstandard1.1 bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml FluentMediator.Microsoft.Extensions.DependencyInjection 0.4.7 Ivan Paulovich Ivan Paulovich Microsoft Extensions for FluentMediator. Microsoft Extensions for FluentMediator. fluent-design;mediator-pattern;ddd-cqrs;message-bus;event-sourcing;event-driven;chain-of-responsibility;chain-methods;pipelines;dotnet-core;craftmanship;tdd;csharp;pipeline-framework;fluent-interface;event-handlers true icon.png https://github.com/ivanpaulovich/FluentMediator en-US true true snupkg True ================================================ FILE: src/FluentMediator.Microsoft.Extensions.DependencyInjection/FluentMediatorExtensions.cs ================================================ using System; using Microsoft.Extensions.DependencyInjection; namespace FluentMediator { /// /// FluentMediatorExtensions /// public static class FluentMediatorExtensions { /// /// Adds the FluentMediator /// /// The ServiceCollection /// Builder /// The changed ServiceCollection public static IServiceCollection AddFluentMediator( this IServiceCollection services, Action setupAction) where TMediator : class, IMediator { var pipelineProviderBuilder = new PipelineProviderBuilder(); setupAction(pipelineProviderBuilder); var pipelineProvider = pipelineProviderBuilder.Build(); services.AddTransient(c => c.GetService); services.AddTransient(c => pipelineProvider); services.AddTransient(); return services; } /// /// Adds the FluentMediator /// /// The ServiceCollection /// Builder /// The changed ServiceCollection public static IServiceCollection AddFluentMediator(this IServiceCollection services, Action setupAction) { var pipelineProviderBuilder = new PipelineProviderBuilder(); setupAction(pipelineProviderBuilder); var pipelineProvider = pipelineProviderBuilder.Build(); services.AddTransient(c => c.GetService); services.AddTransient(c => pipelineProvider); services.AddTransient(); return services; } /// /// Adds the FluentMediator /// /// The ServiceCollection /// Builder /// The changed ServiceCollection public static IServiceCollection AddSingletonFluentMediator( this IServiceCollection services, Action setupAction) { var pipelineProviderBuilder = new PipelineProviderBuilder(); setupAction(pipelineProviderBuilder); var pipelineProvider = pipelineProviderBuilder.Build(); services.AddSingleton(c => pipelineProvider); services.AddSingleton(c => c.GetService); services.AddSingleton(); return services;; } /// /// Adds the FluentMediator /// /// The ServiceCollection /// Builder /// The changed ServiceCollection public static IServiceCollection AddScopedFluentMediator( this IServiceCollection services, Action setupAction) { var pipelineProviderBuilder = new PipelineProviderBuilder(); setupAction(pipelineProviderBuilder); var pipelineProvider = pipelineProviderBuilder.Build(); services.AddScoped(c => pipelineProvider); services.AddScoped(c => c.GetService); services.AddScoped(); return services; } } } ================================================ FILE: test/UnitTests/BuildingMediatorTests.cs ================================================ using System; using FluentMediator; using FluentMediator.Pipelines; using Microsoft.Extensions.DependencyInjection; using UnitTests.PingPong; using Xunit; namespace UnitTests { public class BuildingMediatorTests { [Fact] public void BuildSendAsyncPipeline_ThrowsPipelineAlreadyExistsException() { var services = new ServiceCollection(); var pipelineProviderBuilder = new PipelineProviderBuilder(); pipelineProviderBuilder.On().PipelineAsync() .Return( (handler, req) => handler.MyCustomFooBarAsync(req) ); pipelineProviderBuilder.On().PipelineAsync() .Return( (handler, req) => handler.MyCustomFooBarAsync(req) ); Exception ex = Record.Exception(() => pipelineProviderBuilder.Build()); Assert.NotNull(ex); Assert.IsType(ex); } } } ================================================ FILE: test/UnitTests/MyCustomMediator.cs ================================================ using FluentMediator; namespace UnitTests { public class MyCustomMediator : Mediator { public bool MyCustomPipelineNotFoundHandlerWasCalled = false; public MyCustomMediator(GetService getService, IPipelineProvider pipelines) : base(getService, pipelines) { } protected override void OnPipelineNotFound(PipelineNotFoundEventArgs e) { MyCustomPipelineNotFoundHandlerWasCalled = true; //Do something before raising the event base.OnPipelineNotFound(e); //Do something after raising the event } } } ================================================ FILE: test/UnitTests/PingPong/IPingHandler.cs ================================================ using System.Threading; using System.Threading.Tasks; namespace UnitTests.PingPong { public interface IPingHandler { PingResponse MyCustomFooMethod(PingRequest request); PingResponse MyCustomBarMethod(PingRequest request); Task MyCustomFooBarAsync(PingRequest request); Task MyCancellableForAsync(PingRequest request, CancellationToken cancelationToken); } } ================================================ FILE: test/UnitTests/PingPong/PingHandler.cs ================================================ using System.Threading; using System.Threading.Tasks; namespace UnitTests.PingPong { public class PingHandler : IPingHandler { public PingResponse MyCustomBarMethod(PingRequest request) { return new PingResponse("Pong"); } public PingResponse MyCustomFooMethod(PingRequest request) { return new PingResponse("Pong"); } public Task MyCustomFooBarAsync(PingRequest request) { return Task.FromResult(new PingResponse("Pong")); } public Task MyCancellableForAsync(PingRequest request, CancellationToken cancelationToken) { return Task.FromResult(new PingResponse("Pong")); } } } ================================================ FILE: test/UnitTests/PingPong/PingRequest.cs ================================================ namespace UnitTests.PingPong { public class PingRequest { public string Message { get; } public PingRequest(string message) { Message = message; } } } ================================================ FILE: test/UnitTests/PingPong/PingResponse.cs ================================================ namespace UnitTests.PingPong { public class PingResponse { public string Message { get; } public PingResponse(string message) { Message = message; } } } ================================================ FILE: test/UnitTests/PublishingRequestsTests.cs ================================================ using System.Threading; using System.Threading.Tasks; using FluentMediator; using Microsoft.Extensions.DependencyInjection; using Moq; using UnitTests.PingPong; using Xunit; namespace UnitTests { public sealed class PublishingRequestsTests { [Fact] public void Publish_Calls_Pipeline_Handlers() { var services = new ServiceCollection(); services.AddFluentMediator(builder => { builder.On().Pipeline() .Call((handler, req) => handler.MyCustomFooMethod(req)) .Call((handler, req) => handler.MyCustomBarMethod(req)); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); // // Act // mediator.Publish(ping); pingHandler.Verify(e => e.MyCustomFooMethod(ping), Times.Once); pingHandler.Verify(e => e.MyCustomBarMethod(ping), Times.Once); } [Fact] public async Task PublishAsync_Calls_AsyncPipeline_Handlers() { var services = new ServiceCollection(); services.AddFluentMediator(builder => { builder.On().PipelineAsync() .Call(async(handler, req) => await handler.MyCustomFooBarAsync(req)) .Build(); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Async Ping"); // // Act // await mediator.PublishAsync(ping); pingHandler.Verify(e => e.MyCustomFooBarAsync(ping), Times.Once); } [Fact] public async Task PublishAsync_Calls_CancellablePipeline_Handlers() { var services = new ServiceCollection(); services.AddFluentMediator(builder => { builder.On().CancellablePipelineAsync() .Call(async(handler, req, ct) => await handler.MyCancellableForAsync(req, ct)) .Build(); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var cts = new CancellationTokenSource(); var ping = new PingRequest("Cancellable Async Ping"); // // Act // await mediator.PublishAsync(ping, cts.Token); pingHandler.Verify(e => e.MyCancellableForAsync(ping, It.IsAny()), Times.Once); } [Fact] public async Task PublishAsync_Calls_CancellablePipeline_Handlers2() { var services = new ServiceCollection(); services.AddFluentMediator(builder => { builder.On().CancellablePipelineAsync() .Call(async(handler, req, ct) => await handler.MyCancellableForAsync(req, ct)) .Return( async(handler, req, ct) => await handler.MyCancellableForAsync(req, ct) ); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var cts = new CancellationTokenSource(); var ping = new PingRequest("Cancellable Async Ping"); // // Act // await mediator.PublishAsync(ping, cts.Token); pingHandler.Verify(e => e.MyCancellableForAsync(ping, It.IsAny()), Times.Once); } [Fact] public void Publish_CallsPipelineNotFound_WhenHandlerIsNotSetup() { var services = new ServiceCollection(); // Mediator Without the Handler for PingRequest. services.AddFluentMediator(builder => { }); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); bool myCustomPipelineNotFoundHandlerWasCalled = false; // This is handler is called for every message without a destination pipeline. mediator.PipelineNotFound += (object sender, PipelineNotFoundEventArgs e) => { myCustomPipelineNotFoundHandlerWasCalled = true; }; var cts = new CancellationTokenSource(); var ping = new PingRequest("Cancellable Async Ping"); // Should run without throwing exceptions mediator.Publish(ping); // The method was called :) Assert.True(myCustomPipelineNotFoundHandlerWasCalled); } [Fact] public void Publish_CallsCustomPipelineNotFound_WhenHandlerIsNotSetup() { var services = new ServiceCollection(); // Mediator Without the Handler for PingRequest. services.AddFluentMediator(builder => { }); var provider = services.BuildServiceProvider(); var mediator = (MyCustomMediator) provider.GetRequiredService(); var cts = new CancellationTokenSource(); var ping = new PingRequest("Cancellable Async Ping"); // Should run without throwing exceptions mediator.Publish(ping); // The method was called :) Assert.True(mediator.MyCustomPipelineNotFoundHandlerWasCalled); } } } ================================================ FILE: test/UnitTests/SendingRequestTests.cs ================================================ using System.Threading; using System.Threading.Tasks; using FluentMediator; using FluentMediator.Pipelines; using Microsoft.Extensions.DependencyInjection; using Moq; using UnitTests.PingPong; using Xunit; namespace UnitTests { public class SendingRequestTests { [Fact] public void Send_Without_Return_Throws_ReturnFunctionIsNullException() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On().Pipeline() .Call((handler, req) => handler.MyCustomFooMethod(req)) .Call((handler, req) => handler.MyCustomBarMethod(req)); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var actualEx = Record.Exception( // // Act // () => mediator.Send(ping) ); Assert.IsType(actualEx); } [Fact] public void SendAsync_Without_Return_Throws_ReturnFunctionIsNullException() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On().PipelineAsync() .Call((handler, req) => handler.MyCustomFooBarAsync(req)) .Call((handler, req) => handler.MyCustomFooBarAsync(req)); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var actualEx = Record.ExceptionAsync( // // Act // async() => await mediator.SendAsync(ping) ); Assert.IsType(actualEx.Result); pingHandler.Verify(e => e.MyCustomFooMethod(ping), Times.Never); pingHandler.Verify(e => e.MyCustomBarMethod(ping), Times.Never); } [Fact] public void CancellableSendAsync_Without_Return_Throws_ReturnFunctionIsNullException() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On().CancellablePipelineAsync() .Call((handler, req, ct) => handler.MyCancellableForAsync(req, ct)) .Call((handler, req, ct) => handler.MyCancellableForAsync(req, ct)); }); var pingHandler = new Mock(); services.AddScoped(provider => pingHandler.Object); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var cts = new CancellationTokenSource(); var ping = new PingRequest("Ping"); var actualEx = Record.ExceptionAsync( // // Act // async() => await mediator.SendAsync(ping, cts.Token) ); Assert.IsType(actualEx.Result); } [Fact] public async Task SendAsync_Returns_Response() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On().PipelineAsync() .Return( (handler, req) => handler.MyCustomFooBarAsync(req) ); }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var response = await mediator.SendAsync(ping); Assert.NotNull(response); } [Fact] public void Send_Returns_Response() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On() .Pipeline() .Return( (handler, req) => handler.MyCustomFooMethod(req) ); }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var response = mediator.Send(ping); Assert.NotNull(response); } [Fact] public void Send_Named_PipelineReturns_Response() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On() .Pipeline() .Return( (handler, req) => handler.MyCustomFooMethod(req) ); m.On() .Pipeline("Foo") .Return( (handler, req) => handler.MyCustomFooMethod(req) ); }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var response = mediator.Send(ping, "Foo"); Assert.NotNull(response); } [Fact] public async Task Send_Named_PipelineAsync_Returns_Response() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On() .PipelineAsync() .Return( (handler, req) => handler.MyCustomFooBarAsync(req) ); m.On() .PipelineAsync("Foo") .Return( (handler, req) => handler.MyCustomFooBarAsync(req) ); }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var ping = new PingRequest("Ping"); var response = await mediator.SendAsync(ping, "Foo"); Assert.NotNull(response); } [Fact] public async Task SendCancellable_Named_PipelineReturns_Response() { var services = new ServiceCollection(); services.AddFluentMediator(m => { m.On() .CancellablePipelineAsync() .Return( (handler, req, ct) => handler.MyCancellableForAsync(req, ct) ); m.On() .CancellablePipelineAsync("Foo") .Return( (handler, req, ct) => handler.MyCancellableForAsync(req, ct) ); }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var cts = new CancellationTokenSource(); var ping = new PingRequest("Ping"); var response = await mediator.SendAsync(ping, cts.Token, "Foo"); Assert.NotNull(response); } [Fact] public void Send_Throws_Exception_Null_Requests() { var services = new ServiceCollection(); services.AddFluentMediator(m => { }); services.AddScoped(); var provider = services.BuildServiceProvider(); var mediator = provider.GetRequiredService(); var actualEx = Record.Exception(() => mediator.Send(null!)); Assert.NotNull(actualEx); Assert.IsType(actualEx); } } } ================================================ FILE: test/UnitTests/UnitTests.csproj ================================================ netcoreapp2.2 false enable true 8.0 true