[
  {
    "path": ".editorconfig",
    "content": "root=true\n; EditorConfig helps developers define and maintain consistent\n; coding styles between different editors and IDEs.\n\n; For more visit http://editorconfig.org.\n\n; Choose between lf or rf on \"end_of_line\" property\n[*.proto]\nindent_style=tab\nindent_size=tab\ntab_width=4\n\n[*.{asax,ascx,aspx,cs,cshtml,css,htm,html,js,jsx,master,razor,skin,ts,tsx,vb,xaml,xamlx,xoml}]\nindent_style=space\nindent_size=4\ntab_width=4\n\n[*.{appxmanifest,build,config,csproj,dbml,discomap,dtd,json,jsproj,lsproj,njsproj,nuspec,proj,props,resjson,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}]\nindent_style=space\nindent_size=2\ntab_width=2\n\n[*]\n\n# Standard properties\nend_of_line=native\ninsert_final_newline=false\n\n# Microsoft .NET properties\ncsharp_indent_braces=false\ncsharp_indent_switch_labels=true\ncsharp_new_line_before_catch=true\ncsharp_new_line_before_else=true\ncsharp_new_line_before_finally=true\ncsharp_new_line_before_members_in_object_initializers=false\ncsharp_new_line_before_open_brace=all\ncsharp_new_line_between_query_expression_clauses=true\ncsharp_preferred_modifier_order=public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async:suggestion\ncsharp_preserve_single_line_blocks=true\ncsharp_space_after_cast=true\ncsharp_space_after_colon_in_inheritance_clause=true\ncsharp_space_after_comma=true\ncsharp_space_after_dot=false\ncsharp_space_after_keywords_in_control_flow_statements=true\ncsharp_space_after_semicolon_in_for_statement=true\ncsharp_space_around_binary_operators=before_and_after\ncsharp_space_before_colon_in_inheritance_clause=true\ncsharp_space_before_comma=false\ncsharp_space_before_dot=false\ncsharp_space_before_open_square_brackets=false\ncsharp_space_before_semicolon_in_for_statement=false\ncsharp_space_between_empty_square_brackets=false\ncsharp_space_between_method_call_empty_parameter_list_parentheses=false\ncsharp_space_between_method_call_name_and_opening_parenthesis=false\ncsharp_space_between_method_call_parameter_list_parentheses=false\ncsharp_space_between_method_declaration_empty_parameter_list_parentheses=false\ncsharp_space_between_method_declaration_name_and_open_parenthesis=false\ncsharp_space_between_method_declaration_parameter_list_parentheses=false\ncsharp_space_between_parentheses=false\ncsharp_space_between_square_brackets=false\ncsharp_style_expression_bodied_accessors=true:suggestion\ncsharp_style_expression_bodied_constructors=true:suggestion\ncsharp_style_expression_bodied_methods=true:suggestion\ncsharp_style_expression_bodied_properties=true:suggestion\ncsharp_style_var_elsewhere=true:hint\ncsharp_style_var_for_built_in_types=true:hint\ncsharp_style_var_when_type_is_apparent=true:hint\ncsharp_using_directive_placement=outside_namespace:silent\ndotnet_style_predefined_type_for_locals_parameters_members=true:hint\ndotnet_style_predefined_type_for_member_access=true:hint\ndotnet_style_qualification_for_event=false:hint\ndotnet_style_qualification_for_field=false:hint\ndotnet_style_qualification_for_method=false:hint\ndotnet_style_qualification_for_property=false:hint\ndotnet_style_require_accessibility_modifiers=for_non_interface_members:hint\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.doc  diff=astextplain\n*.DOC\tdiff=astextplain\n*.docx\tdiff=astextplain\n*.DOCX\tdiff=astextplain\n*.dot\tdiff=astextplain\n*.DOT\tdiff=astextplain\n*.pdf\tdiff=astextplain\n*.PDF\tdiff=astextplain\n*.rtf\tdiff=astextplain\n*.RTF\tdiff=astextplain\n\n*.jpg  \tbinary\n*.png \tbinary\n*.gif \tbinary\n\ncore.eol crlf\n\n*.cs diff=csharp \n\n*.csproj merge=union \n*.vbproj merge=union \n*.fsproj merge=union \n*.dbproj merge=union \n*.sln merge=union\n*.slnx merge=union\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  workflow_dispatch: \n  push:\n    branches:\n    - main\n  pull_request:\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n  MINVERBUILDMETADATA: build.${{ github.run_id }}.${{ github.run_attempt}}\npermissions:\n  id-token: write\n  contents: read\n  checks: write\njobs:\n  build:\n    runs-on: windows-latest\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v4.2.0\n      with:\n        fetch-depth: 0\n        filter: tree:0\n    - name: Setup dotnet\n      uses: actions/setup-dotnet@v4\n      with:\n        dotnet-version: |\n          8.0.x\n          9.0.x\n          10.0.x\n    - name: Install NuGetKeyVaultSignTool\n      run: dotnet tool install --global NuGetKeyVaultSignTool\n    - name: Build and Test\n      run: ./Build.ps1\n      shell: pwsh\n    - name: Report Test Results\n      uses: dorny/test-reporter@v1.9.1\n      if: success() || failure()\n      with:\n        name: Test Results (Windows)\n        path: '**/TestResults/**/*.trx'\n        reporter: dotnet-trx\n    - name: Get package version\n      id: version\n      shell: pwsh\n      run: |\n        $pkg = Get-ChildItem ./artifacts -Filter \"MediatR.*.nupkg\" | Select-Object -First 1\n        $version = $pkg.BaseName -replace '^MediatR\\.', ''\n        \"version=$version\" | Out-File -FilePath $env:GITHUB_OUTPUT -Append\n    - name: Generate SBOM\n      shell: pwsh\n      run: |\n        dotnet tool install --global Microsoft.Sbom.DotNetTool\n        sbom-tool generate `\n          -b ./artifacts `\n          -bc ./src/MediatR `\n          -pn MediatR `\n          -pv ${{ steps.version.outputs.version }} `\n          -ps \"Lucky Penny Software LLC\" `\n          -nsb https://mediatr.io\n    - name: Push to MyGet\n      if: github.ref == 'refs/heads/main'\n      env:\n        NUGET_URL: https://f.feedz.io/lucky-penny-software/mediatr/nuget/index.json\n        NUGET_API_KEY: ${{ secrets.FEEDZIO_ACCESS_TOKEN }}\n      run: ./Push.ps1\n      shell: pwsh\n    - name: Artifacts\n      uses: actions/upload-artifact@v4\n      with:\n        name: artifacts\n        path: artifacts/**/*\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n    - '*.*.*'\nenv:\n  DOTNET_NOLOGO: true\n  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true\n  MINVERBUILDMETADATA: build.${{ github.run_id }}.${{ github.run_attempt}}\npermissions:\n  id-token: write\n  contents: read\n  checks: write\njobs:\n  build:\n    strategy:\n      matrix: \n        os: [windows-2025]\n      fail-fast: false\n    runs-on: windows-2025\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v4\n      with:\n        fetch-depth: 0\n        filter: tree:0\n    - name: Azure Login via OIDC\n      uses: azure/login@v2\n      with:\n        client-id: ${{ secrets.AZURE_CLIENT_ID }}\n        tenant-id: ${{ secrets.AZURE_TENANT_ID }}\n        subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}\n    - name: Setup dotnet\n      uses: actions/setup-dotnet@v4\n      with:\n        dotnet-version: |\n          8.0.x\n          9.0.x\n          10.0.x\n    - name: Install NuGetKeyVaultSignTool\n      run: dotnet tool install --global NuGetKeyVaultSignTool\n    - name: Build and Test\n      run: ./Build.ps1\n      shell: pwsh\n    - name: Report Test Results\n      uses: dorny/test-reporter@v1.9.1\n      if: always()\n      with:\n        name: Test Results (Windows)\n        path: '**/TestResults/**/*.trx'\n        reporter: dotnet-trx\n    - name: Get package version\n      id: version\n      shell: pwsh\n      run: |\n        $pkg = Get-ChildItem ./artifacts -Filter \"MediatR.*.nupkg\" | Select-Object -First 1\n        $version = $pkg.BaseName -replace '^MediatR\\.', ''\n        \"version=$version\" | Out-File -FilePath $env:GITHUB_OUTPUT -Append\n    - name: Generate SBOM\n      shell: pwsh\n      run: |\n        dotnet tool install --global Microsoft.Sbom.DotNetTool\n        sbom-tool generate `\n          -b ./artifacts `\n          -bc ./src/MediatR `\n          -pn MediatR `\n          -pv ${{ steps.version.outputs.version }} `\n          -ps \"Lucky Penny Software LLC\" `\n          -nsb https://mediatr.io\n    - name: Sign packages\n      run: |-\n        foreach ($f in Get-ChildItem \"./artifacts\" -Filter \"*.nupkg\") {\n          NuGetKeyVaultSignTool sign $f.FullName --file-digest sha256 --timestamp-rfc3161 http://timestamp.digicert.com --azure-key-vault-managed-identity --azure-key-vault-url ${{ secrets.AZURE_KEYVAULT_URI }} --azure-key-vault-certificate ${{ secrets.CODESIGN_CERT_NAME }}\n        }\n    - name: Push to MyGet\n      env:\n        NUGET_URL: https://f.feedz.io/lucky-penny-software/mediatr/nuget/index.json\n        NUGET_API_KEY: ${{ secrets.FEEDZIO_ACCESS_TOKEN }}\n      run: ./Push.ps1\n      shell: pwsh\n    - name: Push to NuGet\n      env:\n        NUGET_URL: https://api.nuget.org/v3/index.json\n        NUGET_API_KEY: ${{ secrets.MEDIATR_NUGET_API_KEY }}\n      run: ./Push.ps1\n      shell: pwsh\n    - name: Artifacts\n      uses: actions/upload-artifact@v4\n      with:\n        name: artifacts\n        path: artifacts/**/*\n"
  },
  {
    "path": ".github/workflows/triage-issues.yml",
    "content": "# https://github.com/actions/stale\n\nname: \"Stale issue & PR handler\"\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: \"0 12 * * *\"\n\nenv:\n  ISSUES_DAYS_BEFORE_CLOSE: 14\n  PR_DAYS_BEFORE_CLOSE: 14\n  ISSUES_DAYS_BEFORE_STALE: 60\n  PR_DAYS_BEFORE_STALE: 28\n\njobs:\n  issues:\n    name: \"Close stale issues and PRs\"\n    runs-on: \"ubuntu-latest\"\n    steps:\n      - uses: \"actions/stale@v6.0.0\"\n        with:\n          stale-issue-label: \"stale\"\n          stale-issue-message: \"This issue is stale because it has been open ${{ env.ISSUES_DAYS_BEFORE_STALE }} days with no activity. Remove stale label or comment or this will be closed in ${{ env.ISSUES_DAYS_BEFORE_CLOSE }} days.\"\n          close-issue-message: 'This issue was closed because it has been stalled for ${{ env.ISSUES_DAYS_BEFORE_CLOSE }} days with no activity.'\n          days-before-close: \"${{ env.ISSUES_DAYS_BEFORE_CLOSE }}\"\n          days-before-stale: \"${{ env.ISSUES_DAYS_BEFORE_STALE }}\"\n          exempt-issue-assignees: true\n          exempt-issue-labels: 'awaiting-approval,work-in-progress,up-for-grabs'\n          stale-pr-label: \"stale\"\n          stale-pr-message: 'This PR is stale because it has been open ${{ env.PR_DAYS_BEFORE_STALE }} days with no activity. Remove stale label or comment or this will be closed in ${{ env.PR_DAYS_BEFORE_CLOSE }} days.'\n          close-pr-message: 'This PR was closed because it has been stalled for ${{ env.PR_DAYS_BEFORE_CLOSE }} days with no activity.'\n          days-before-pr-close: \"${{ env.PR_DAYS_BEFORE_CLOSE }}\"\n          days-before-pr-stale: \"${{ env.PR_DAYS_BEFORE_STALE }}\"\n          exempt-all-pr-assignees: true\n          exempt-pr-labels: 'awaiting-approval,work-in-progress'"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User-specific files\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\nbuild/\nbld/\n[Bb]in/\n[Oo]bj/\nartifacts/\n\n# Visual Studio 2015 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUNIT\n*.VisualState.xml\nTestResult.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# DNX\nproject.lock.json\nartifacts/\n\n*_i.c\n*_p.c\n*_i.h\n*.ilk\n*.meta\n*.obj\n*.pch\n*.pdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opensdf\n*.sdf\n*.cachefile\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# JustCode is a .NET coding add-in\n.JustCode\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n*.ncrunchsolution\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# TODO: Comment the next line if you want to checkin your web deploy settings \n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# NuGet Packages\n*.nupkg\n# The packages folder can be ignored because of Package Restore\n**/packages/*\n# except build/, which is used as an MSBuild target.\n!**/packages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/packages/repositories.config\n\n# Windows Azure Build Output\ncsx/\n*.build.csdef\n\n# Windows Store app package directory\nAppPackages/\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!*.[Cc]ache/\n\n# Others\nClientBin/\n[Ss]tyle[Cc]op.*\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.pfx\n*.publishsettings\nnode_modules/\norleans.codegen.cs\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\n\n# SQL Server files\n*.mdf\n*.ldf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Project Rider\n*.iml\n.idea\n\n# Apple\n.DS_Store"
  },
  {
    "path": "Build.ps1",
    "content": "# Taken from psake https://github.com/psake/psake\n\n<#\n.SYNOPSIS\n  This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode\n  to see if an error occcured. If an error is detected then an exception is thrown.\n  This function allows you to run command-line programs without having to\n  explicitly check the $lastexitcode variable.\n.EXAMPLE\n  exec { svn info $repository_trunk } \"Error executing SVN. Please verify SVN command-line client is installed\"\n#>\nfunction Exec\n{\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,\n        [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd)\n    )\n    & $cmd\n    if ($lastexitcode -ne 0) {\n        throw (\"Exec: \" + $errorMessage)\n    }\n}\n\n$artifacts = \".\\artifacts\"\n\nif(Test-Path $artifacts) { Remove-Item $artifacts -Force -Recurse }\n\nexec { & dotnet clean -c Release }\n\nexec { & dotnet build -c Release }\n\nexec { & dotnet test -c Release --no-build -l trx --verbosity=normal }\n\nexec { & dotnet pack .\\src\\MediatR\\MediatR.csproj -c Release -o $artifacts --no-build }\n\n"
  },
  {
    "path": "BuildContracts.ps1",
    "content": "# Taken from psake https://github.com/psake/psake\n\n<#\n.SYNOPSIS\n  This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode\n  to see if an error occcured. If an error is detected then an exception is thrown.\n  This function allows you to run command-line programs without having to\n  explicitly check the $lastexitcode variable.\n.EXAMPLE\n  exec { svn info $repository_trunk } \"Error executing SVN. Please verify SVN command-line client is installed\"\n#>\nfunction Exec\n{\n    [CmdletBinding()]\n    param(\n        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,\n        [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd)\n    )\n    & $cmd\n    if ($lastexitcode -ne 0) {\n        throw (\"Exec: \" + $errorMessage)\n    }\n}\n\n$artifacts = \".\\artifacts\"\n$contracts = \".\\src\\MediatR.Contracts\\MediatR.Contracts.csproj\"\n\nif(Test-Path $artifacts) { Remove-Item $artifacts -Force -Recurse }\n\nexec { & dotnet clean $contracts -c Release }\n\nexec { & dotnet build $contracts -c Release -p:ContinuousIntegrationBuild=true }\n\nexec { & dotnet pack $contracts -c Release -o $artifacts --no-build }\n"
  },
  {
    "path": "Directory.Build.props",
    "content": "<Project>\n  <PropertyGroup>\n    <IsMac>$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_OSX())))</IsMac>\n    <IsWindows>$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::get_Windows())))</IsWindows>\n\n    <LangVersion>13.0</LangVersion>\n    <NoWarn>$(NoWarn);CS1701;CS1702;CS1591;NU1900</NoWarn>\n    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "LICENSE.md",
    "content": "By accessing code under the [Lucky Penny Software GitHub Organization](https://github.com/LuckyPennySoftware) (Lucky Penny Software) here, you are agreeing to the following licensing terms.\nIf you do not agree to these terms, do not access Lucky Penny Software code.\n\nYour license to Lucky Penny Software source code and/or binaries is governed by the Reciprocal Public License 1.5 (RPL1.5) license as described here: \n\nhttps://opensource.org/license/rpl-1-5/\n\nIf you do not wish to release the source of software you build using Lucky Penny Software source code and/or binaries under the terms above, you may use Lucky Penny Software source code and/or binaries under the License Agreement described here:\n\nhttps://luckypennysoftware.com/license"
  },
  {
    "path": "MediatR.slnx",
    "content": "<Solution>\n  <Folder Name=\"/samples/\">\n    <Project Path=\"samples/MediatR.Examples.AspNetCore/MediatR.Examples.AspNetCore.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.Autofac/MediatR.Examples.Autofac.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.DryIoc/MediatR.Examples.DryIoc.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.Lamar/MediatR.Examples.Lamar.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.LightInject/MediatR.Examples.LightInject.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.PublishStrategies/MediatR.Examples.PublishStrategies.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.SimpleInjector/MediatR.Examples.SimpleInjector.csproj\" />\n    <Project Path=\"samples/MediatR.Examples.Stashbox/MediatR.Examples.Stashbox.csproj\" />\n    <Project Path=\"samples/MediatR.Examples/MediatR.Examples.csproj\" />\n  </Folder>\n  <Folder Name=\"/Solution Items/\">\n    <File Path=\".editorconfig\" />\n    <File Path=\".github/workflows/ci.yml\" />\n    <File Path=\".github/workflows/release.yml\" />\n    <File Path=\"Build.ps1\" />\n    <File Path=\"BuildContracts.ps1\" />\n    <File Path=\"Directory.Build.props\" />\n    <File Path=\"MediatR.snk\" />\n    <File Path=\"Push.ps1\" />\n    <File Path=\"README.md\" />\n  </Folder>\n  <Folder Name=\"/src/\">\n    <Project Path=\"src/MediatR.Contracts/MediatR.Contracts.csproj\" />\n    <Project Path=\"src/MediatR/MediatR.csproj\" />\n  </Folder>\n  <Folder Name=\"/test/\">\n    <Project Path=\"test/MediatR.Benchmarks/MediatR.Benchmarks.csproj\" />\n    <Project Path=\"test/MediatR.DependencyInjectionTests/MediatR.DependencyInjectionTests.csproj\" />\n    <Project Path=\"test/MediatR.Tests/MediatR.Tests.csproj\" />\n  </Folder>\n</Solution>\n"
  },
  {
    "path": "NuGet.Config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<configuration>\n  <packageSources>\n    <add key=\"nuget.org\" value=\"https://api.nuget.org/v3/index.json\" protocolVersion=\"3\" />\n  </packageSources>\n</configuration>"
  },
  {
    "path": "Push.ps1",
    "content": "$scriptName = $MyInvocation.MyCommand.Name\n$artifacts = \"./artifacts\"\n\nif ([string]::IsNullOrEmpty($Env:NUGET_API_KEY)) {\n    Write-Host \"${scriptName}: NUGET_API_KEY is empty or not set. Skipped pushing package(s).\"\n} else {\n    Get-ChildItem $artifacts -Filter \"*.nupkg\" | ForEach-Object {\n        Write-Host \"$($scriptName): Pushing $($_.Name)\"\n        dotnet nuget push $_ --source $Env:NUGET_URL --api-key $Env:NUGET_API_KEY --skip-duplicate\n        if ($lastexitcode -ne 0) {\n            throw (\"Exec: \" + $errorMessage)\n        }\n    }\n}\n"
  },
  {
    "path": "README.md",
    "content": "MediatR\n=======\n\n![CI](https://github.com/LuckyPennySoftware/MediatR/workflows/CI/badge.svg)\n[![NuGet](https://img.shields.io/nuget/dt/mediatr.svg)](https://www.nuget.org/packages/mediatr) \n[![NuGet](https://img.shields.io/nuget/vpre/mediatr.svg)](https://www.nuget.org/packages/mediatr)\n[![MyGet (dev)](https://img.shields.io/myget/mediatr-ci/v/MediatR.svg)](https://myget.org/gallery/mediatr-ci)\n\nSimple mediator implementation in .NET\n\nIn-process messaging with no dependencies.\n\nSupports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance.\n\nExamples in the [wiki](https://github.com/LuckyPennySoftware/MediatR/wiki).\n\n### Installing MediatR\n\nYou should install [MediatR with NuGet](https://www.nuget.org/packages/MediatR):\n\n    Install-Package MediatR\n    \nOr via the .NET Core command line interface:\n\n    dotnet add package MediatR\n\nEither commands, from Package Manager Console or .NET Core CLI, will download and install MediatR and all required dependencies.\n\n### Using Contracts-Only Package\n\nTo reference only the contracts for MediatR, which includes:\n\n- `IRequest` (including generic variants)\n- `INotification`\n- `IStreamRequest`\n\nAdd a package reference to [MediatR.Contracts](https://www.nuget.org/packages/MediatR.Contracts)\n\nThis package is useful in scenarios where your MediatR contracts are in a separate assembly/project from handlers. Example scenarios include:\n- API contracts\n- GRPC contracts\n- Blazor\n\n### Registering with `IServiceCollection`\n\nMediatR supports `Microsoft.Extensions.DependencyInjection.Abstractions` directly. To register various MediatR services and handlers:\n\n```\nservices.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Startup>());\n```\n\nor with an assembly:\n\n```\nservices.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly));\n```\n\nThis registers:\n\n- `IMediator` as transient\n- `ISender` as transient\n- `IPublisher` as transient\n- `IRequestHandler<,>` concrete implementations as transient\n- `IRequestHandler<>` concrete implementations as transient\n- `INotificationHandler<>` concrete implementations as transient\n- `IStreamRequestHandler<>` concrete implementations as transient\n- `IRequestExceptionHandler<,,>` concrete implementations as transient\n- `IRequestExceptionAction<,>)` concrete implementations as transient\n\nThis also registers open generic implementations for:\n\n- `INotificationHandler<>`\n- `IRequestExceptionHandler<,,>`\n- `IRequestExceptionAction<,>`\n\nTo register behaviors, stream behaviors, pre/post processors:\n\n```csharp\nservices.AddMediatR(cfg => {\n    cfg.RegisterServicesFromAssembly(typeof(Startup).Assembly);\n    cfg.AddBehavior<PingPongBehavior>();\n    cfg.AddStreamBehavior<PingPongStreamBehavior>();\n    cfg.AddRequestPreProcessor<PingPreProcessor>();\n    cfg.AddRequestPostProcessor<PingPongPostProcessor>();\n    cfg.AddOpenBehavior(typeof(GenericBehavior<,>));\n    });\n```\n\nWith additional methods for open generics and overloads for explicit service types.\n\n### Setting the license key\n\nYou can set the license key when registering MediatR:\n\n```csharp\nservices.AddMediatR(cfg => \n{\n    cfg.LicenseKey = \"<license key here>\";\n})\n```\n\nOr if not using Microsoft.Extensions.DependencyInjection:\n\n```csharp\nMediator.LicenseKey = \"<license key here>\";\n```\n\n> [!TIP]\n> The license key does not need to be set on client applications (such as Blazor WASM).\n> Turn off the license warning by configuring logging in your logging start configuration:\n> `builder.Logging.AddFilter(\"LuckyPennySoftware.MediatR.License\", LogLevel.None);`\n\nYou can register for your license key at [MediatR.io](https://mediatr.io)\n"
  },
  {
    "path": "samples/MediatR.Examples/ConstrainedRequestPostProcessor.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Examples;\n\npublic class ConstrainedRequestPostProcessor<TRequest, TResponse>\n    : IRequestPostProcessor<TRequest, TResponse>\n    where TRequest : Ping\n{\n    private readonly TextWriter _writer;\n\n    public ConstrainedRequestPostProcessor(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Process(TRequest request, TResponse response, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"- All Done with Ping\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/Exceptions.cs",
    "content": "using System;\n\nnamespace MediatR.Examples.ExceptionHandler;\n\npublic class ConnectionException : Exception { }\n\npublic class ForbiddenException : ConnectionException { }\n\npublic class ResourceNotFoundException : ConnectionException { }\n\npublic class ServerException : Exception { }"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/ExceptionsHandlers.cs",
    "content": "using MediatR.Pipeline;\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.ExceptionHandler;\n\npublic class CommonExceptionHandler : IRequestExceptionHandler<PingResource, Pong, Exception>\n{\n    private readonly TextWriter _writer;\n\n    public CommonExceptionHandler(TextWriter writer) => _writer = writer;\n\n    public async Task Handle(PingResource request,\n        Exception exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(CommonExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n\npublic class ConnectionExceptionHandler : IRequestExceptionHandler<PingResource, Pong, ConnectionException>\n{\n    private readonly TextWriter _writer;\n\n    public ConnectionExceptionHandler(TextWriter writer) => _writer = writer;\n\n    public async Task Handle(PingResource request,\n        ConnectionException exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(ConnectionExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n\npublic class AccessDeniedExceptionHandler : IRequestExceptionHandler<PingResource, Pong, ForbiddenException>\n{\n    private readonly TextWriter _writer;\n\n    public AccessDeniedExceptionHandler(TextWriter writer) => _writer = writer;\n\n    public async Task Handle(PingResource request,\n        ForbiddenException exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(AccessDeniedExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n\npublic class ServerExceptionHandler : IRequestExceptionHandler<PingNewResource, Pong, ServerException>\n{\n    private readonly TextWriter _writer;\n\n    public ServerExceptionHandler(TextWriter writer) => _writer = writer;\n\n    public virtual async Task Handle(PingNewResource request,\n        ServerException exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(ServerExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/ExceptionsHandlersOverrides.cs",
    "content": "using MediatR.Pipeline;\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.ExceptionHandler.Overrides;\n\npublic class CommonExceptionHandler : IRequestExceptionHandler<PingResourceTimeout, Pong, Exception>\n{\n    private readonly TextWriter _writer;\n\n    public CommonExceptionHandler(TextWriter writer) => _writer = writer;\n\n    public async Task Handle(PingResourceTimeout request,\n        Exception exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(CommonExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n\npublic class ServerExceptionHandler : ExceptionHandler.ServerExceptionHandler\n{\n    private readonly TextWriter _writer;\n\n    public ServerExceptionHandler(TextWriter writer) : base(writer) => _writer = writer;\n\n    public override async Task Handle(PingNewResource request,\n        ServerException exception,\n        RequestExceptionHandlerState<Pong> state,\n        CancellationToken cancellationToken)\n    {\n        // Exception type name must be written in messages by LogExceptionAction before\n        // Exception handler type name required because it is checked later in messages\n        await _writer.WriteLineAsync($\"---- Exception Handler: '{typeof(ServerExceptionHandler).FullName}'\").ConfigureAwait(false);\n        \n        state.SetHandled(new Pong());\n    }\n}\n"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/Handlers.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.ExceptionHandler;\n\npublic class PingResourceHandler : IRequestHandler<PingResource, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingResourceHandler(TextWriter writer) => _writer = writer;\n\n    public Task<Pong> Handle(PingResource request, CancellationToken cancellationToken)\n    {\n        throw new ResourceNotFoundException();\n    }\n}\n\npublic class PingNewResourceHandler : IRequestHandler<PingNewResource, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingNewResourceHandler(TextWriter writer) => _writer = writer;\n\n    public Task<Pong> Handle(PingNewResource request, CancellationToken cancellationToken)\n    {\n        throw new ServerException();\n    }\n}\n\npublic class PingResourceTimeoutHandler : IRequestHandler<PingResourceTimeout, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingResourceTimeoutHandler(TextWriter writer) => _writer = writer;\n\n    public Task<Pong> Handle(PingResourceTimeout request, CancellationToken cancellationToken)\n    {\n        throw new TaskCanceledException();\n    }\n}\n\npublic class PingResourceTimeoutOverrideHandler : IRequestHandler<Overrides.PingResourceTimeout, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingResourceTimeoutOverrideHandler(TextWriter writer) => _writer = writer;\n\n    public Task<Pong> Handle(Overrides.PingResourceTimeout request, CancellationToken cancellationToken)\n    {\n        throw new TaskCanceledException();\n    }\n}\n\npublic class PingProtectedResourceHandler : IRequestHandler<PingProtectedResource, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingProtectedResourceHandler(TextWriter writer) => _writer = writer;\n\n    public Task<Pong> Handle(PingProtectedResource request, CancellationToken cancellationToken)\n    {\n        throw new ForbiddenException();\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/LogExceptionAction.cs",
    "content": "using MediatR.Pipeline;\nusing System;\nusing System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.ExceptionHandler;\n\npublic class LogExceptionAction : IRequestExceptionAction<Ping, Exception>\n{\n    private readonly TextWriter _writer;\n\n    public LogExceptionAction(TextWriter writer) => _writer = writer;\n\n    public Task Execute(Ping request, Exception exception, CancellationToken cancellationToken) \n        => _writer.WriteLineAsync($\"--- Exception: '{exception.GetType().FullName}'\");\n}"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/Requests.cs",
    "content": "namespace MediatR.Examples.ExceptionHandler;\n\npublic class PingResource : Ping { }\n\npublic class PingNewResource : Ping { }\n\npublic class PingResourceTimeout : PingResource { }\n\npublic class PingProtectedResource : PingResource { }"
  },
  {
    "path": "samples/MediatR.Examples/ExceptionHandler/RequestsOverrides.cs",
    "content": "namespace MediatR.Examples.ExceptionHandler.Overrides;\n\npublic class PingResourceTimeout : ExceptionHandler.PingResourceTimeout { }"
  },
  {
    "path": "samples/MediatR.Examples/GenericHandler.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples;\n\npublic class GenericHandler : INotificationHandler<INotification>\n{\n    private readonly TextWriter _writer;\n\n    public GenericHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(INotification notification, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"Got notified.\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/GenericPipelineBehavior.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples;\n\npublic class GenericPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n{\n    private readonly TextWriter _writer;\n\n    public GenericPipelineBehavior(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n    {\n        await _writer.WriteLineAsync(\"-- Handling Request\");\n        var response = await next();\n        await  _writer.WriteLineAsync(\"-- Finished Request\");\n        return response;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/GenericRequestPostProcessor.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Examples;\n\npublic class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>\n{\n    private readonly TextWriter _writer;\n\n    public GenericRequestPostProcessor(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Process(TRequest request, TResponse response, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"- All Done\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/GenericRequestPreProcessor.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Examples;\n\npublic class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>\n{\n    private readonly TextWriter _writer;\n\n    public GenericRequestPreProcessor(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Process(TRequest request, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"- Starting Up\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Jing.cs",
    "content": "namespace MediatR.Examples;\n\npublic class Jing : IRequest\n{\n    public string Message { get; set; }\n}"
  },
  {
    "path": "samples/MediatR.Examples/JingHandler.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples;\n\npublic class JingHandler : IRequestHandler<Jing>\n{\n    private readonly TextWriter _writer;\n\n    public JingHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(Jing request, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync($\"--- Handled Jing: {request.Message}, no Jong\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/MediatR.Examples.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\MediatR\\MediatR.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples/Ping.cs",
    "content": "﻿namespace MediatR.Examples;\n\npublic class Ping : IRequest<Pong>\n{\n    public string Message { get; set; }\n}"
  },
  {
    "path": "samples/MediatR.Examples/PingHandler.cs",
    "content": "using System.IO;\nusing System.Threading;\n\nnamespace MediatR.Examples;\n\nusing System.Threading.Tasks;\n\npublic class PingHandler : IRequestHandler<Ping, Pong>\n{\n    private readonly TextWriter _writer;\n\n    public PingHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public async Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n    {\n        await _writer.WriteLineAsync($\"--- Handled Ping: {request.Message}\");\n        return new Pong { Message = request.Message + \" Pong\" };\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Pinged.cs",
    "content": "namespace MediatR.Examples;\n\npublic class Pinged : INotification\n{\n         \n}"
  },
  {
    "path": "samples/MediatR.Examples/PingedHandler.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Examples;\n\nusing System.IO;\nusing System.Threading.Tasks;\n\npublic class PingedHandler : INotificationHandler<Pinged>\n{\n    private readonly TextWriter _writer;\n\n    public PingedHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(Pinged notification, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"Got pinged async.\");\n    }\n}\n\npublic class PongedHandler : INotificationHandler<Ponged>\n{\n    private readonly TextWriter _writer;\n\n    public PongedHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(Ponged notification, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"Got ponged async.\");\n    }\n}\n\npublic class ConstrainedPingedHandler<TNotification> : INotificationHandler<TNotification>\n    where TNotification : Pinged\n{\n    private readonly TextWriter _writer;\n\n    public ConstrainedPingedHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(TNotification notification, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"Got pinged constrained async.\");\n    }\n}\n\npublic class PingedAlsoHandler : INotificationHandler<Pinged>\n{\n    private readonly TextWriter _writer;\n\n    public PingedAlsoHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public Task Handle(Pinged notification, CancellationToken cancellationToken)\n    {\n        return _writer.WriteLineAsync(\"Got pinged also async.\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Pong.cs",
    "content": "﻿namespace MediatR.Examples;\n\npublic class Pong\n{\n    public string Message { get; set; }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Ponged.cs",
    "content": "﻿namespace MediatR.Examples;\n\npublic class Ponged : INotification\n{\n\n}"
  },
  {
    "path": "samples/MediatR.Examples/Runner.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Text;\n\nnamespace MediatR.Examples;\n\nusing MediatR.Examples.ExceptionHandler;\nusing System.IO;\nusing System.Threading.Tasks;\n\npublic static class Runner\n{\n    public static async Task Run(IMediator mediator, WrappingWriter writer, string projectName, bool testStreams = false)\n    {\n        await writer.WriteLineAsync(\"===============\");\n        await writer.WriteLineAsync(projectName);\n        await writer.WriteLineAsync(\"===============\");\n        await writer.WriteLineAsync();\n\n        await writer.WriteLineAsync(\"Sending Ping...\");\n        var pong = await mediator.Send(new Ping { Message = \"Ping\" });\n        await writer.WriteLineAsync(\"Received: \" + pong.Message);\n        await writer.WriteLineAsync();\n\n        await writer.WriteLineAsync(\"Publishing Pinged...\");\n        await mediator.Publish(new Pinged());\n        await writer.WriteLineAsync();\n\n        await writer.WriteLineAsync(\"Publishing Ponged...\");\n        var failedPong = false;\n        try\n        {\n            await mediator.Publish(new Ponged());\n        }\n        catch (Exception e)\n        {\n            failedPong = true;\n            await writer.WriteLineAsync(e.ToString());\n        }\n        await writer.WriteLineAsync();\n\n        var failedJing = false;\n        await writer.WriteLineAsync(\"Sending Jing...\");\n        try\n        {\n            await mediator.Send(new Jing { Message = \"Jing\" });\n        }\n        catch (Exception e)\n        {\n            failedJing = true;\n            await writer.WriteLineAsync(e.ToString());\n        }\n        await writer.WriteLineAsync();\n\n        bool failedSing = false;\n        if (testStreams)\n        {\n            await writer.WriteLineAsync(\"Sending Sing...\");\n            try\n            {\n                int i = 0;\n                await foreach (Song s in mediator.CreateStream(new Sing { Message = \"Sing\" }))\n                {\n                    if (i == 0) {\n                        failedSing = !(s.Message.Contains(\"Singing do\"));\n                    }\n                    else if (i == 1)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing re\"));\n                    }\n                    else if (i == 2)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing mi\"));\n                    }\n                    else if (i == 3)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing fa\"));\n                    }\n                    else if (i == 4)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing so\"));\n                    }\n                    else if (i == 5)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing la\"));\n                    }\n                    else if (i == 6)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing ti\"));\n                    }\n                    else if (i == 7)\n                    {\n                        failedSing = !(s.Message.Contains(\"Singing do\"));\n                    }\n\n                    failedSing = failedSing || (++i) > 10;\n                }\n            }\n            catch (Exception e)\n            {\n                failedSing = true;\n                await writer.WriteLineAsync(e.ToString());\n            }\n            await writer.WriteLineAsync();\n        }\n\n        var isHandlerForSameExceptionWorks = await IsHandlerForSameExceptionWorks(mediator, writer).ConfigureAwait(false);\n        var isHandlerForBaseExceptionWorks = await IsHandlerForBaseExceptionWorks(mediator, writer).ConfigureAwait(false);\n        var isHandlerForLessSpecificExceptionWorks = await IsHandlerForLessSpecificExceptionWorks(mediator, writer).ConfigureAwait(false);\n        var isPreferredHandlerForBaseExceptionWorks = await IsPreferredHandlerForBaseExceptionWorks(mediator, writer).ConfigureAwait(false);\n        var isOverriddenHandlerForBaseExceptionWorks = await IsOverriddenHandlerForBaseExceptionWorks(mediator, writer).ConfigureAwait(false);\n\n        await writer.WriteLineAsync(\"---------------\");\n        var contents = writer.Contents;\n        var order = new[] {\n            contents.IndexOf(\"- Starting Up\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"-- Handling Request\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"--- Handled Ping\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"-- Finished Request\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"- All Done\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"- All Done with Ping\", StringComparison.OrdinalIgnoreCase),\n        };\n\n        var streamOrder = new[] {\n            contents.IndexOf(\"-- Handling StreamRequest\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"--- Handled Sing: Sing, Song\", StringComparison.OrdinalIgnoreCase),\n            contents.IndexOf(\"-- Finished StreamRequest\", StringComparison.OrdinalIgnoreCase),\n        };\n\n        var results = new RunResults\n        {\n            RequestHandlers = contents.Contains(\"--- Handled Ping:\"),\n            VoidRequestsHandlers = contents.Contains(\"--- Handled Jing:\"),\n            PipelineBehaviors = contents.Contains(\"-- Handling Request\"),\n            RequestPreProcessors = contents.Contains(\"- Starting Up\"),\n            RequestPostProcessors = contents.Contains(\"- All Done\"),\n            ConstrainedGenericBehaviors = contents.Contains(\"- All Done with Ping\") && !failedJing,\n            OrderedPipelineBehaviors = order.SequenceEqual(order.OrderBy(i => i)),\n            NotificationHandler = contents.Contains(\"Got pinged async\"),\n            MultipleNotificationHandlers = contents.Contains(\"Got pinged async\") && contents.Contains(\"Got pinged also async\"),\n            ConstrainedGenericNotificationHandler = contents.Contains(\"Got pinged constrained async\") && !failedPong,\n            CovariantNotificationHandler = contents.Contains(\"Got notified\"),\n            HandlerForSameException = isHandlerForSameExceptionWorks,\n            HandlerForBaseException = isHandlerForBaseExceptionWorks,\n            HandlerForLessSpecificException = isHandlerForLessSpecificExceptionWorks,\n            PreferredHandlerForBaseException = isPreferredHandlerForBaseExceptionWorks,\n            OverriddenHandlerForBaseException = isOverriddenHandlerForBaseExceptionWorks,\n\n            // Streams\n            StreamRequestHandlers = contents.Contains(\"--- Handled Sing: Sing, Song\") && !failedSing,\n            StreamPipelineBehaviors = contents.Contains(\"-- Handling StreamRequest\"),\n            StreamOrderedPipelineBehaviors = streamOrder.SequenceEqual(streamOrder.OrderBy(i => i))\n        };\n\n        await writer.WriteLineAsync($\"Request Handler....................................................{(results.RequestHandlers ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Void Request Handler...............................................{(results.VoidRequestsHandlers ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Pipeline Behavior..................................................{(results.PipelineBehaviors ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Pre-Processor......................................................{(results.RequestPreProcessors ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Post-Processor.....................................................{(results.RequestPostProcessors ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Constrained Post-Processor.........................................{(results.ConstrainedGenericBehaviors ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Ordered Behaviors..................................................{(results.OrderedPipelineBehaviors ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Notification Handler...............................................{(results.NotificationHandler ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Notification Handlers..............................................{(results.MultipleNotificationHandlers ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Constrained Notification Handler...................................{(results.ConstrainedGenericNotificationHandler ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Covariant Notification Handler.....................................{(results.CovariantNotificationHandler ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Handler for inherited request with same exception used.............{(results.HandlerForSameException ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Handler for inherited request with base exception used.............{(results.HandlerForBaseException ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Handler for request with less specific exception used by priority..{(results.HandlerForLessSpecificException ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Preferred handler for inherited request with base exception used...{(results.PreferredHandlerForBaseException ? \"Y\" : \"N\")}\");\n        await writer.WriteLineAsync($\"Overridden handler for inherited request with same exception used..{(results.OverriddenHandlerForBaseException ? \"Y\" : \"N\")}\");\n\n        if (testStreams)\n        {\n            await writer.WriteLineAsync($\"Stream Request Handler.............................................{(results.StreamRequestHandlers ? \"Y\" : \"N\")}\");\n            await writer.WriteLineAsync($\"Stream Pipeline Behavior...........................................{(results.StreamPipelineBehaviors ? \"Y\" : \"N\")}\");\n            await writer.WriteLineAsync($\"Stream Ordered Behaviors...........................................{(results.StreamOrderedPipelineBehaviors ? \"Y\" : \"N\")}\");\n        }\n\n        await writer.WriteLineAsync();\n    }\n\n    private static async Task<bool> IsHandlerForSameExceptionWorks(IMediator mediator, WrappingWriter writer)\n    {\n        var isHandledCorrectly = false;\n\n        await writer.WriteLineAsync(\"Checking handler to catch exact exception...\");\n        try\n        {\n            await mediator.Send(new PingProtectedResource { Message = \"Ping to protected resource\" });\n            isHandledCorrectly = IsExceptionHandledBy<ForbiddenException, AccessDeniedExceptionHandler>(writer);\n        }\n        catch (Exception e)\n        {\n            await writer.WriteLineAsync(e.Message);\n        }\n        await writer.WriteLineAsync();\n\n        return isHandledCorrectly;\n    }\n\n    private static async Task<bool> IsHandlerForBaseExceptionWorks(IMediator mediator, WrappingWriter writer)\n    {\n        var isHandledCorrectly = false;\n\n        await writer.WriteLineAsync(\"Checking shared handler to catch exception by base type...\");\n        try\n        {\n            await mediator.Send(new PingResource { Message = \"Ping to missed resource\" });\n            isHandledCorrectly = IsExceptionHandledBy<ResourceNotFoundException, ConnectionExceptionHandler>(writer);\n        }\n        catch (Exception e)\n        {\n            await writer.WriteLineAsync(e.Message);\n        }\n        await writer.WriteLineAsync();\n\n        return isHandledCorrectly;\n    }\n        \n    private static async Task<bool> IsHandlerForLessSpecificExceptionWorks(IMediator mediator, WrappingWriter writer)\n    {\n        var isHandledCorrectly = false;\n\n        await writer.WriteLineAsync(\"Checking base handler to catch any exception...\");\n        try\n        {\n            await mediator.Send(new PingResourceTimeout { Message = \"Ping to ISS resource\" });\n            isHandledCorrectly = IsExceptionHandledBy<TaskCanceledException, CommonExceptionHandler> (writer);\n        }\n        catch (Exception e)\n        {\n            await writer.WriteLineAsync(e.Message);\n        }\n        await writer.WriteLineAsync();\n\n        return isHandledCorrectly;\n    }\n\n    private static async Task<bool> IsPreferredHandlerForBaseExceptionWorks(IMediator mediator, WrappingWriter writer)\n    {\n        var isHandledCorrectly = false;\n\n        await writer.WriteLineAsync(\"Selecting preferred handler to handle exception...\");\n\n        try\n        {\n            await mediator.Send(new ExceptionHandler.Overrides.PingResourceTimeout { Message = \"Ping to ISS resource (preferred)\" });\n            isHandledCorrectly = IsExceptionHandledBy<TaskCanceledException, ExceptionHandler.Overrides.CommonExceptionHandler> (writer);\n        }\n        catch (Exception e)\n        {\n            await writer.WriteLineAsync(e.Message);\n        }\n        await writer.WriteLineAsync();\n\n        return isHandledCorrectly;\n    }\n\n    private static async Task<bool> IsOverriddenHandlerForBaseExceptionWorks(IMediator mediator, WrappingWriter writer)\n    {\n        var isHandledCorrectly = false;\n\n        await writer.WriteLineAsync(\"Selecting new handler to handle exception...\");\n\n        try\n        {\n            await mediator.Send(new PingNewResource { Message = \"Ping to ISS resource (override)\" });\n            isHandledCorrectly = IsExceptionHandledBy<ServerException, ExceptionHandler.Overrides.ServerExceptionHandler> (writer);\n        }\n        catch (Exception e)\n        {\n            await writer.WriteLineAsync(e.Message);\n        }\n        await writer.WriteLineAsync();\n\n        return isHandledCorrectly;\n    }\n\n    private static bool IsExceptionHandledBy<TException, THandler>(WrappingWriter writer)\n        where TException : Exception\n    {\n        var messages = writer.Contents.Split(new[] { \"\\r\\n\", \"\\r\", \"\\n\" }, StringSplitOptions.None).ToList();\n        if (messages.Count - 3 < 0)\n            return false;\n\n        // Note: For this handler type to be found in messages, it must be written in messages by LogExceptionAction\n        return messages[messages.Count - 2].Contains(typeof(THandler).FullName)\n            // Note: For this exception type to be found in messages, exception must be written in all tested exception handlers\n               && messages[messages.Count - 3].Contains(typeof(TException).FullName);\n    }\n}\n\npublic class RunResults\n{\n    public bool RequestHandlers { get; set; }\n    public bool VoidRequestsHandlers { get; set; }\n    public bool PipelineBehaviors { get; set; }\n    public bool RequestPreProcessors { get; set; }\n    public bool RequestPostProcessors { get; set; }\n    public bool OrderedPipelineBehaviors { get; set; }\n    public bool ConstrainedGenericBehaviors { get; set; }\n    public bool NotificationHandler { get; set; }\n    public bool MultipleNotificationHandlers { get; set; }\n    public bool CovariantNotificationHandler { get; set; }\n    public bool ConstrainedGenericNotificationHandler { get; set; }\n    public bool HandlerForSameException { get; set; }\n    public bool HandlerForBaseException { get; set; }\n    public bool HandlerForLessSpecificException { get; set; }\n    public bool PreferredHandlerForBaseException { get; set; }\n    public bool OverriddenHandlerForBaseException { get; set; }\n\n    // Stream results\n    public bool StreamRequestHandlers { get; set; }\n    public bool StreamPipelineBehaviors { get; set; }\n    public bool StreamOrderedPipelineBehaviors { get; set; }\n}\n\npublic class WrappingWriter : TextWriter\n{\n    private readonly TextWriter _innerWriter;\n    private readonly StringBuilder _stringWriter = new StringBuilder();\n\n    public WrappingWriter(TextWriter innerWriter)\n    {\n        _innerWriter = innerWriter;\n    }\n\n    public override void Write(char value)\n    {\n        _stringWriter.Append(value);\n        _innerWriter.Write(value);\n    }\n\n    public override Task WriteLineAsync(string value)\n    {\n        _stringWriter.AppendLine(value);\n        return _innerWriter.WriteLineAsync(value);\n    }\n\n    public override Encoding Encoding => _innerWriter.Encoding;\n\n    public string Contents => _stringWriter.ToString();\n}\n"
  },
  {
    "path": "samples/MediatR.Examples/Streams/GenericStreamPipelineBehavior.cs",
    "content": "using System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples;\n\npublic class GenericStreamPipelineBehavior<TRequest, TResponse> : IStreamPipelineBehavior<TRequest, TResponse>\n{\n    private readonly TextWriter _writer;\n\n    public GenericStreamPipelineBehavior(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public async IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, [EnumeratorCancellation]CancellationToken cancellationToken)\n    {\n        await _writer.WriteLineAsync(\"-- Handling StreamRequest\");\n        await foreach (var response in next().WithCancellation(cancellationToken).ConfigureAwait(false))\n        {\n            yield return response;\n        }\n        await _writer.WriteLineAsync(\"-- Finished StreamRequest\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Streams/Sing.cs",
    "content": "namespace MediatR.Examples;\n\npublic class Sing : IStreamRequest<Song>\n{\n    public string Message { get; set; }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Streams/SingHandler.cs",
    "content": "using System.Collections.Generic;\nusing System.IO;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples;\n\npublic class SingHandler : IStreamRequestHandler<Sing, Song>\n{\n    private readonly TextWriter _writer;\n\n    public SingHandler(TextWriter writer)\n    {\n        _writer = writer;\n    }\n\n    public async IAsyncEnumerable<Song> Handle(Sing request, [EnumeratorCancellation]CancellationToken cancellationToken)\n    {\n        await _writer.WriteLineAsync($\"--- Handled Sing: {request.Message}, Song\");\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing do\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing re\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing mi\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing fa\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing so\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing la\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing ti\" });\n        yield return await Task.Run(() => new Song { Message = request.Message + \"ing do\" });\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples/Streams/Song.cs",
    "content": "namespace MediatR.Examples;\n\npublic class Song\n{\n    public string Message { get; set; }\n}"
  },
  {
    "path": "samples/MediatR.Examples.AspNetCore/MediatR.Examples.AspNetCore.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.AspNetCore/Program.cs",
    "content": "using System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\nusing Microsoft.Extensions.DependencyInjection;\n\n\nnamespace MediatR.Examples.AspNetCore;\n\npublic static class Program\n{\n    public static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n        return Runner.Run(mediator, writer, \"ASP.NET Core DI\", testStreams: true);\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var services = new ServiceCollection();\n\n        services.AddSingleton<TextWriter>(writer);\n\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly, typeof(Sing).Assembly);\n        });\n\n        services.AddScoped(typeof(IStreamRequestHandler<Sing, Song>), typeof(SingHandler));\n\n        services.AddScoped(typeof(IPipelineBehavior<,>), typeof(GenericPipelineBehavior<,>));\n        services.AddScoped(typeof(IRequestPreProcessor<>), typeof(GenericRequestPreProcessor<>));\n        services.AddScoped(typeof(IRequestPostProcessor<,>), typeof(GenericRequestPostProcessor<,>));\n        services.AddScoped(typeof(IStreamPipelineBehavior<,>), typeof(GenericStreamPipelineBehavior<,>));\n\n        var provider = services.BuildServiceProvider();\n\n        return provider.GetRequiredService<IMediator>();\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.Autofac/MediatR.Examples.Autofac.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Autofac\" Version=\"8.4.0\" />\n    <PackageReference Include=\"Autofac.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.Autofac/Program.cs",
    "content": "using Autofac.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.Autofac;\n\nusing global::Autofac;\nusing MediatR.Pipeline;\nusing System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading.Tasks;\n\ninternal static class Program\n{\n    public static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"Autofac\", testStreams: true);\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n\n        var builder = new ContainerBuilder();\n\n        builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();\n\n        var mediatrOpenTypes = new[]\n        {\n                typeof(IRequestHandler<,>),\n                typeof(IRequestExceptionHandler<,,>),\n                typeof(IRequestExceptionAction<,>),\n                typeof(INotificationHandler<>),\n                typeof(IStreamRequestHandler<,>)\n            };\n\n        foreach (var mediatrOpenType in mediatrOpenTypes)\n        {\n            builder\n                .RegisterAssemblyTypes(typeof(Ping).GetTypeInfo().Assembly)\n                .AsClosedTypesOf(mediatrOpenType)\n                // when having a single class implementing several handler types\n                // this call will cause a handler to be called twice\n                // in general you should try to avoid having a class implementing for instance `IRequestHandler<,>` and `INotificationHandler<>`\n                // the other option would be to remove this call\n                // see also https://github.com/LuckyPennySoftware/MediatR/issues/462\n                .AsImplementedInterfaces();\n        }\n\n        builder.RegisterInstance(writer).As<TextWriter>();\n\n        // It appears Autofac returns the last registered types first\n        builder.RegisterGeneric(typeof(GenericStreamPipelineBehavior<,>)).As(typeof(IStreamPipelineBehavior<,>));\n\n        builder.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));\n        builder.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));\n        builder.RegisterGeneric(typeof(RequestExceptionActionProcessorBehavior<,>))\n            .As(typeof(IPipelineBehavior<,>));\n        builder.RegisterGeneric(typeof(RequestExceptionProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>));\n        builder.RegisterGeneric(typeof(GenericRequestPreProcessor<>)).As(typeof(IRequestPreProcessor<>));\n        builder.RegisterGeneric(typeof(GenericRequestPostProcessor<,>)).As(typeof(IRequestPostProcessor<,>));\n        builder.RegisterGeneric(typeof(GenericPipelineBehavior<,>)).As(typeof(IPipelineBehavior<,>));\n        builder.RegisterGeneric(typeof(ConstrainedRequestPostProcessor<,>)).As(typeof(IRequestPostProcessor<,>));\n        builder.RegisterGeneric(typeof(ConstrainedPingedHandler<>)).As(typeof(INotificationHandler<>));\n\n\n        var services = new ServiceCollection();\n        \n        builder.Populate(services);\n\n        // The below returns:\n        //  - RequestPreProcessorBehavior\n        //  - RequestPostProcessorBehavior\n        //  - GenericPipelineBehavior\n        //  - GenericStreamPipelineBehavior\n        //  - RequestExceptionActionProcessorBehavior\n        //  - RequestExceptionProcessorBehavior\n\n        //var behaviors = container\n        //    .Resolve<IEnumerable<IPipelineBehavior<Ping, Pong>>>()\n        //    .ToList();\n\n        var container = builder.Build();\n        var serviceProvider = new AutofacServiceProvider(container);\n        var mediator = serviceProvider.GetRequiredService<IMediator>();\n\n        return mediator;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.DryIoc/MediatR.Examples.DryIoc.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"DryIoc.Microsoft.DependencyInjection\" Version=\"8.0.0-preview-04\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.DryIoc/Program.cs",
    "content": "using System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing DryIoc;\nusing DryIoc.Microsoft.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.DryIoc;\n\nclass Program\n{\n    static Task Main()\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"DryIoc\");\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var container = new Container();\n        // Since Mediator has multiple constructors, consider adding rule to allow that\n        // var container = new Container(rules => rules.With(FactoryMethod.ConstructorWithResolvableArguments))\n\n        container.Use<TextWriter>(writer);\n\n        //Pipeline works out of the box here\n\n        container.RegisterMany(new[] { typeof(IMediator).GetAssembly(), typeof(Ping).GetAssembly() }, Registrator.Interfaces);\n        //Without the container having FactoryMethod.ConstructorWithResolvableArguments commented above\n        //You must select the desired constructor\n        container.Register<IMediator, Mediator>(made: Made.Of(() => new Mediator(Arg.Of<IServiceProvider>())));\n\n        var services = new ServiceCollection();\n\n        var adapterContainer = container.WithDependencyInjectionAdapter(services);\n\n        return adapterContainer.GetRequiredService<IMediator>();\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.Lamar/MediatR.Examples.Lamar.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net10.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Lamar\" Version=\"15.0.1\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection.Abstractions\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.Lamar/Program.cs",
    "content": "using System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Lamar;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Examples.Lamar;\n\nclass Program\n{\n    static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"Lamar\");\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var container = new Container(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.AssemblyContainingType<Ping>();\n                scanner.ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>));\n                scanner.ConnectImplementationsToTypesClosing(typeof(INotificationHandler<>));\n                scanner.ConnectImplementationsToTypesClosing(typeof(IRequestExceptionAction<,>));\n                scanner.ConnectImplementationsToTypesClosing(typeof(IRequestExceptionHandler<,,>));\n            });\n\n            //Pipeline\n            cfg.For(typeof(IPipelineBehavior<,>)).Add(typeof(RequestExceptionProcessorBehavior<,>));\n            cfg.For(typeof(IPipelineBehavior<,>)).Add(typeof(RequestExceptionActionProcessorBehavior<,>));\n            cfg.For(typeof(IPipelineBehavior<,>)).Add(typeof(RequestPreProcessorBehavior<,>));\n            cfg.For(typeof(IPipelineBehavior<,>)).Add(typeof(RequestPostProcessorBehavior<,>));\n            cfg.For(typeof(IPipelineBehavior<,>)).Add(typeof(GenericPipelineBehavior<,>));\n            cfg.For(typeof(IRequestPreProcessor<>)).Add(typeof(GenericRequestPreProcessor<>));\n            cfg.For(typeof(IRequestPostProcessor<,>)).Add(typeof(GenericRequestPostProcessor<,>));\n            cfg.For(typeof(IRequestPostProcessor<,>)).Add(typeof(ConstrainedRequestPostProcessor<,>));\n\n            //Constrained notification handlers\n            cfg.For(typeof(INotificationHandler<>)).Add(typeof(ConstrainedPingedHandler<>));\n\n            // This is the default but let's be explicit. At most we should be container scoped.\n            cfg.For<IMediator>().Use<Mediator>().Transient();\n\n            cfg.For<TextWriter>().Use(writer);\n        });\n\n\n        var mediator = container.GetInstance<IMediator>();\n\n        return mediator;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.LightInject/MediatR.Examples.LightInject.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"LightInject\" Version=\"7.0.1\" />\n    <PackageReference Include=\"LightInject.Microsoft.DependencyInjection\" Version=\"4.0.3\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.LightInject/Program.cs",
    "content": "using System;\nusing System.IO;\nusing System.Reflection;\nusing System.Threading.Tasks;\nusing LightInject;\nusing LightInject.Microsoft.DependencyInjection;\nusing MediatR.Pipeline;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.LightInject;\n\nclass Program\n{\n    static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"LightInject\");\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var serviceContainer = new ServiceContainer(ContainerOptions.Default.WithMicrosoftSettings());\n        serviceContainer.Register<IMediator, Mediator>();            \n        serviceContainer.RegisterInstance<TextWriter>(writer);\n\n        serviceContainer.RegisterAssembly(typeof(Ping).GetTypeInfo().Assembly, (serviceType, implementingType) =>\n            serviceType.IsConstructedGenericType &&\n            (\n                serviceType.GetGenericTypeDefinition() == typeof(IRequestHandler<,>) ||\n                serviceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)\n            ));\n                    \n        serviceContainer.RegisterOrdered(typeof(IPipelineBehavior<,>),\n            new[]\n            {\n                typeof(RequestPreProcessorBehavior<,>),\n                typeof(RequestPostProcessorBehavior<,>),\n                typeof(GenericPipelineBehavior<,>)\n            }, type => null);\n\n            \n        serviceContainer.RegisterOrdered(typeof(IRequestPostProcessor<,>),\n            new[]\n            {\n                typeof(GenericRequestPostProcessor<,>),\n                typeof(ConstrainedRequestPostProcessor<,>)\n            }, type => null);\n                   \n        serviceContainer.Register(typeof(IRequestPreProcessor<>), typeof(GenericRequestPreProcessor<>));\n\n        var services = new ServiceCollection();\n        var provider = serviceContainer.CreateServiceProvider(services);\n        return provider.GetRequiredService<IMediator>(); \n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/AsyncPingedHandler.cs",
    "content": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.PublishStrategies;\n\npublic class AsyncPingedHandler : INotificationHandler<Pinged>\n{\n    public AsyncPingedHandler(string name)\n    {\n        Name = name;\n    }\n\n    public string Name { get; set; }\n\n    public async Task Handle(Pinged notification, CancellationToken cancellationToken)\n    {\n        if (Name == \"2\")\n        {\n            throw new ArgumentException(\"Name cannot be '2'\");\n        }\n\n        Console.WriteLine($\"[AsyncPingedHandler {Name}] {DateTime.Now:HH:mm:ss.fff} : Pinged\");\n        await Task.Delay(100).ConfigureAwait(false);\n        Console.WriteLine($\"[AsyncPingedHandler {Name}] {DateTime.Now:HH:mm:ss.fff} : After pinged\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/CustomMediator.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.PublishStrategies;\n\npublic class CustomMediator : Mediator\n{\n    private readonly Func<IEnumerable<NotificationHandlerExecutor>, INotification, CancellationToken, Task> _publish;\n\n    public CustomMediator(IServiceProvider serviceFactory, Func<IEnumerable<NotificationHandlerExecutor>, INotification, CancellationToken, Task> publish) : base(serviceFactory) \n        => _publish = publish;\n\n    protected override Task PublishCore(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken) \n        => _publish(handlerExecutors, notification, cancellationToken);\n}"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/MediatR.Examples.PublishStrategies.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net10.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\MediatR\\MediatR.csproj\" />\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/Program.cs",
    "content": "﻿using System;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.PublishStrategies;\n\nclass Program\n{\n    static async Task Main(string[] args)\n    {\n        var services = new ServiceCollection();\n\n        services.AddSingleton<Publisher>();\n\n        services.AddTransient<INotificationHandler<Pinged>>(sp => new SyncPingedHandler(\"1\"));\n        services.AddTransient<INotificationHandler<Pinged>>(sp => new AsyncPingedHandler(\"2\"));\n        services.AddTransient<INotificationHandler<Pinged>>(sp => new AsyncPingedHandler(\"3\"));\n        services.AddTransient<INotificationHandler<Pinged>>(sp => new SyncPingedHandler(\"4\"));\n\n        var provider = services.BuildServiceProvider();\n\n        var publisher = provider.GetRequiredService<Publisher>();\n\n        var pinged = new Pinged();\n\n        foreach (PublishStrategy strategy in Enum.GetValues(typeof(PublishStrategy)))\n        {\n            Console.WriteLine($\"Strategy: {strategy}\");\n            Console.WriteLine(\"----------\");\n\n            try\n            {\n                await publisher.Publish(pinged, strategy);\n            }\n            catch (Exception ex)\n            {\n                Console.WriteLine($\"{ex.GetType()}: {ex.Message}\");\n            }\n\n            await Task.Delay(1000);\n            Console.WriteLine(\"----------\");\n        }\n\n        Console.WriteLine(\"done\");\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/PublishStrategy.cs",
    "content": "namespace MediatR.Examples.PublishStrategies;\n\n/// <summary>\n/// Strategy to use when publishing notifications\n/// </summary>\npublic enum PublishStrategy\n{\n    /// <summary>\n    /// Run each notification handler after one another. Returns when all handlers are finished. In case of any exception(s), they will be captured in an AggregateException.\n    /// </summary>\n    SyncContinueOnException = 0,\n\n    /// <summary>\n    /// Run each notification handler after one another. Returns when all handlers are finished or an exception has been thrown. In case of an exception, any handlers after that will not be run.\n    /// </summary>\n    SyncStopOnException = 1,\n\n    /// <summary>\n    /// Run all notification handlers asynchronously. Returns when all handlers are finished. In case of any exception(s), they will be captured in an AggregateException.\n    /// </summary>\n    Async = 2,\n\n    /// <summary>\n    /// Run each notification handler on its own thread using Task.Run(). Returns immediately and does not wait for any handlers to finish. Note that you cannot capture any exceptions, even if you await the call to Publish.\n    /// </summary>\n    ParallelNoWait = 3,\n\n    /// <summary>\n    /// Run each notification handler on its own thread using Task.Run(). Returns when all threads (handlers) are finished. In case of any exception(s), they are captured in an AggregateException by Task.WhenAll.\n    /// </summary>\n    ParallelWhenAll = 4,\n\n    /// <summary>\n    /// Run each notification handler on its own thread using Task.Run(). Returns when any thread (handler) is finished. Note that you cannot capture any exceptions (See msdn documentation of Task.WhenAny)\n    /// </summary>\n    ParallelWhenAny = 5,\n}\n"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/Publisher.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.PublishStrategies;\n\npublic class Publisher\n{\n    private readonly IServiceProvider _serviceFactory;\n\n    public Publisher(IServiceProvider serviceFactory)\n    {\n        _serviceFactory = serviceFactory;\n\n        PublishStrategies[PublishStrategy.Async] = new CustomMediator(_serviceFactory, AsyncContinueOnException);\n        PublishStrategies[PublishStrategy.ParallelNoWait] = new CustomMediator(_serviceFactory, ParallelNoWait);\n        PublishStrategies[PublishStrategy.ParallelWhenAll] = new CustomMediator(_serviceFactory, ParallelWhenAll);\n        PublishStrategies[PublishStrategy.ParallelWhenAny] = new CustomMediator(_serviceFactory, ParallelWhenAny);\n        PublishStrategies[PublishStrategy.SyncContinueOnException] = new CustomMediator(_serviceFactory, SyncContinueOnException);\n        PublishStrategies[PublishStrategy.SyncStopOnException] = new CustomMediator(_serviceFactory, SyncStopOnException);\n    }\n\n    public IDictionary<PublishStrategy, IMediator> PublishStrategies = new Dictionary<PublishStrategy, IMediator>();\n    public PublishStrategy DefaultStrategy { get; set; } = PublishStrategy.SyncContinueOnException;\n\n    public Task Publish<TNotification>(TNotification notification)\n    {\n        return Publish(notification, DefaultStrategy, default(CancellationToken));\n    }\n\n    public Task Publish<TNotification>(TNotification notification, PublishStrategy strategy)\n    {\n        return Publish(notification, strategy, default(CancellationToken));\n    }\n\n    public Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken)\n    {\n        return Publish(notification, DefaultStrategy, cancellationToken);\n    }\n\n    public Task Publish<TNotification>(TNotification notification, PublishStrategy strategy, CancellationToken cancellationToken)\n    {\n        if (!PublishStrategies.TryGetValue(strategy, out var mediator))\n        {\n            throw new ArgumentException($\"Unknown strategy: {strategy}\");\n        }\n\n        return mediator.Publish(notification, cancellationToken);\n    }\n\n    private Task ParallelWhenAll(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        var tasks = new List<Task>();\n\n        foreach (var handler in handlers)\n        {\n            tasks.Add(Task.Run(() => handler.HandlerCallback(notification, cancellationToken)));\n        }\n\n        return Task.WhenAll(tasks);\n    }\n\n    private Task ParallelWhenAny(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        var tasks = new List<Task>();\n\n        foreach (var handler in handlers)\n        {\n            tasks.Add(Task.Run(() => handler.HandlerCallback(notification, cancellationToken)));\n        }\n\n        return Task.WhenAny(tasks);\n    }\n\n    private Task ParallelNoWait(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        foreach (var handler in handlers)\n        {\n            Task.Run(() => handler.HandlerCallback(notification, cancellationToken));\n        }\n\n        return Task.CompletedTask;\n    }\n\n    private async Task AsyncContinueOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        var tasks = new List<Task>();\n        var exceptions = new List<Exception>();\n\n        foreach (var handler in handlers)\n        {\n            try\n            {\n                tasks.Add(handler.HandlerCallback(notification, cancellationToken));\n            }\n            catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))\n            {\n                exceptions.Add(ex);\n            }\n        }\n\n        try\n        {\n            await Task.WhenAll(tasks).ConfigureAwait(false);\n        }\n        catch (AggregateException ex)\n        {\n            exceptions.AddRange(ex.Flatten().InnerExceptions);\n        }\n        catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))\n        {\n            exceptions.Add(ex);\n        }\n\n        if (exceptions.Any())\n        {\n            throw new AggregateException(exceptions);\n        }\n    }\n\n    private async Task SyncStopOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        foreach (var handler in handlers)\n        {\n            await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);\n        }\n    }\n\n    private async Task SyncContinueOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)\n    {\n        var exceptions = new List<Exception>();\n\n        foreach (var handler in handlers)\n        {\n            try\n            {\n                await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);\n            }\n            catch (AggregateException ex)\n            {\n                exceptions.AddRange(ex.Flatten().InnerExceptions);\n            }\n            catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))\n            {\n                exceptions.Add(ex);\n            }\n        }\n\n        if (exceptions.Any())\n        {\n            throw new AggregateException(exceptions);\n        }\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.PublishStrategies/SyncPingedHandler.cs",
    "content": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Examples.PublishStrategies;\n\npublic class SyncPingedHandler : INotificationHandler<Pinged>\n{\n    public SyncPingedHandler(string name)\n    {\n        Name = name;\n    }\n\n    public string Name { get; set; }\n\n    public Task Handle(Pinged notification, CancellationToken cancellationToken)\n    {\n        if (Name == \"2\")\n        {\n            throw new ArgumentException(\"Name cannot be '2'\");\n        }\n\n        Console.WriteLine($\"[SyncPingedHandler {Name}] {DateTime.Now:HH:mm:ss.fff} : Pinged\");\n        Thread.Sleep(100);\n        Console.WriteLine($\"[SyncPingedHandler {Name}] {DateTime.Now:HH:mm:ss.fff} : After pinged\");\n        return Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.SimpleInjector/MediatR.Examples.SimpleInjector.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"SimpleInjector\" Version=\"5.5.0\" />\n    <PackageReference Include=\"SimpleInjector.Integration.ServiceCollection\" Version=\"5.5.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.SimpleInjector/Program.cs",
    "content": "using System.IO;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.SimpleInjector;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing global::SimpleInjector;\n\ninternal static class Program\n{\n    private static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"SimpleInjector\", true);\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var container = new Container();\n\n        var services = new ServiceCollection();\n\n        services\n            .AddSimpleInjector(container);\n\n        var assemblies = GetAssemblies().ToArray();\n        container.RegisterSingleton<IMediator, Mediator>();\n        container.Register(typeof(IRequestHandler<,>), assemblies);\n\n        RegisterHandlers(container, typeof(INotificationHandler<>), assemblies);\n        RegisterHandlers(container, typeof(IRequestExceptionAction<,>), assemblies);\n        RegisterHandlers(container, typeof(IRequestExceptionHandler<,,>), assemblies);\n        RegisterHandlers(container, typeof(IStreamRequestHandler<,>), assemblies);\n\n        container.Register(() => (TextWriter) writer, Lifestyle.Singleton);\n\n        //Pipeline\n        container.Collection.Register(typeof(IPipelineBehavior<,>), new[]\n        {\n            typeof(RequestExceptionProcessorBehavior<,>),\n            typeof(RequestExceptionActionProcessorBehavior<,>),\n            typeof(RequestPreProcessorBehavior<,>),\n            typeof(RequestPostProcessorBehavior<,>),\n            typeof(GenericPipelineBehavior<,>)\n        });\n        container.Collection.Register(typeof(IRequestPreProcessor<>), new[] { typeof(GenericRequestPreProcessor<>) });\n        container.Collection.Register(typeof(IRequestPostProcessor<,>), new[] { typeof(GenericRequestPostProcessor<,>), typeof(ConstrainedRequestPostProcessor<,>) });\n        container.Collection.Register(typeof(IStreamPipelineBehavior<,>), new[]\n        {\n            typeof(GenericStreamPipelineBehavior<,>)\n        });\n\n        var serviceProvider = services.BuildServiceProvider().UseSimpleInjector(container);\n\n        container.RegisterInstance<IServiceProvider>(container);\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        return mediator;\n    }\n\n    private static void RegisterHandlers(Container container, Type collectionType, Assembly[] assemblies)\n    {\n        // we have to do this because by default, generic type definitions (such as the Constrained Notification Handler) won't be registered\n        var handlerTypes = container.GetTypesToRegister(collectionType, assemblies, new TypesToRegisterOptions\n        {\n            IncludeGenericTypeDefinitions = true,\n            IncludeComposites = false,\n        });\n\n        container.Collection.Register(collectionType, handlerTypes);\n    }\n\n    private static IEnumerable<Assembly> GetAssemblies()\n    {\n        yield return typeof(IMediator).GetTypeInfo().Assembly;\n        yield return typeof(Ping).GetTypeInfo().Assembly;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.Stashbox/MediatR.Examples.Stashbox.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <OutputType>Exe</OutputType>\n    <TargetFramework>net10.0</TargetFramework>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Stashbox\" Version=\"5.17.1\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.Stashbox/Program.cs",
    "content": "﻿using Stashbox;\nusing Stashbox.Configuration;\nusing System;\nusing System.IO;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Examples.Stashbox;\n\nclass Program\n{\n    static Task Main()\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n        return Runner.Run(mediator, writer, \"Stashbox\", testStreams: true);\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var container = new StashboxContainer()\n            .RegisterInstance<TextWriter>(writer)\n            .RegisterAssemblies(new[] { typeof(Mediator).Assembly, typeof(Ping).Assembly }, \n                serviceTypeSelector: Rules.ServiceRegistrationFilters.Interfaces, registerSelf: false);\n\n        return container.GetRequiredService<IMediator>();\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.Windsor/ContravariantFilter.cs",
    "content": "﻿namespace MediatR.Examples.Windsor;\n\nusing System;\nusing System.Linq;\nusing System.Reflection;\nusing Castle.MicroKernel;\n\npublic class ContravariantFilter : IHandlersFilter\n{\n    public bool HasOpinionAbout(Type service)\n    {\n        if (!service.IsGenericType)\n            return false;\n\n        var genericType = service.GetGenericTypeDefinition();\n        var genericArguments = genericType.GetGenericArguments();\n        return genericArguments.Count() == 1\n               && genericArguments.Single().GenericParameterAttributes.HasFlag(GenericParameterAttributes.Contravariant);\n    }\n\n    public IHandler[] SelectHandlers(Type service, IHandler[] handlers)\n    {\n        return handlers;\n    }\n}"
  },
  {
    "path": "samples/MediatR.Examples.Windsor/MediatR.Examples.Windsor.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net6.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MediatR.Examples\\MediatR.Examples.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Castle.Windsor\" Version=\"5.1.2\" />\n    <PackageReference Include=\"Castle.Windsor.Extensions.DependencyInjection\" Version=\"5.1.2\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/MediatR.Examples.Windsor/Program.cs",
    "content": "using System.Linq;\nusing System.Threading.Tasks;\nusing Castle.MicroKernel.Resolvers.SpecializedResolvers;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Examples.Windsor;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing Castle.MicroKernel;\nusing Castle.MicroKernel.Registration;\nusing Castle.Windsor;\n\ninternal class Program\n{\n    private static Task Main(string[] args)\n    {\n        var writer = new WrappingWriter(Console.Out);\n        var mediator = BuildMediator(writer);\n\n        return Runner.Run(mediator, writer, \"Castle.Windsor\", true);\n    }\n\n    private static IMediator BuildMediator(WrappingWriter writer)\n    {\n        var container = new WindsorContainer();\n        container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));\n        container.Kernel.AddHandlersFilter(new ContravariantFilter());\n\n        // *** The default lifestyle for Windsor is Singleton\n        // *** If you are using ASP.net, it's better to register your services with 'Per Web Request LifeStyle'.\n\n        var fromAssemblyContainingPing = Classes.FromAssemblyContaining<Ping>();\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IRequestHandler<,>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(INotificationHandler<>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestExceptionProcessorBehavior<,>)));\n        container.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestExceptionActionProcessorBehavior<,>)));\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IRequestExceptionAction<,>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IRequestExceptionHandler<,,>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IStreamRequestHandler<,>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IRequestPreProcessor<>)).WithServiceAllInterfaces().AllowMultipleMatches());\n        container.Register(fromAssemblyContainingPing.BasedOn(typeof(IRequestPostProcessor<,>)).WithServiceAllInterfaces().AllowMultipleMatches());\n\n        container.Register(Component.For<IMediator>().ImplementedBy<Mediator>());\n        container.Register(Component.For<TextWriter>().Instance(writer));\n        //container.Register(Component.For<ServiceFactory>().UsingFactoryMethod<ServiceFactory>(k => (type =>\n        //{\n        //    var enumerableType = type\n        //        .GetInterfaces()\n        //        .Concat(new[] { type })\n        //        .FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));\n\n        //    var service = enumerableType?.GetGenericArguments()?[0];\n        //    var resolvedType = enumerableType != null ? k.ResolveAll(service) : k.Resolve(type);\n        //    var genericArguments = service?.GetGenericArguments();\n\n        //    // Handle exceptions even using the base request types for IRequestExceptionHandler<,,>\n        //    var isRequestExceptionHandler = service?.GetGenericTypeDefinition()\n        //        ?.IsAssignableTo(typeof(IRequestExceptionHandler<,,>)) ?? false;\n        //    if (isRequestExceptionHandler)\n        //        return ResolveRequestExceptionHandler(k, type, service, resolvedType, genericArguments);\n\n        //    // Handle exceptions even using the base request types for IRequestExceptionAction<,>\n        //    var isRequestExceptionAction = service?.GetGenericTypeDefinition()\n        //        ?.IsAssignableTo(typeof(IRequestExceptionAction<,>)) ?? false;\n        //    if (isRequestExceptionAction)\n        //        return ResolveRequestExceptionAction(k, type, service, resolvedType, genericArguments);\n            \n        //    return resolvedType;\n        //})));\n\n        //Pipeline\n        container.Register(Component.For(typeof(IStreamPipelineBehavior<,>)).ImplementedBy(typeof(GenericStreamPipelineBehavior<,>)));\n        container.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestPreProcessorBehavior<,>)).NamedAutomatically(\"PreProcessorBehavior\"));\n        container.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(RequestPostProcessorBehavior<,>)).NamedAutomatically(\"PostProcessorBehavior\"));\n        container.Register(Component.For(typeof(IPipelineBehavior<,>)).ImplementedBy(typeof(GenericPipelineBehavior<,>)).NamedAutomatically(\"Pipeline\"));\n        container.Register(Component.For(typeof(IRequestPreProcessor<>)).ImplementedBy(typeof(GenericRequestPreProcessor<>)).NamedAutomatically(\"PreProcessor\"));\n        container.Register(Component.For(typeof(IRequestPostProcessor<,>)).ImplementedBy(typeof(GenericRequestPostProcessor<,>)).NamedAutomatically(\"PostProcessor\"));\n        container.Register(Component.For(typeof(IRequestPostProcessor<,>), typeof(ConstrainedRequestPostProcessor<,>)).NamedAutomatically(\"ConstrainedRequestPostProcessor\"));\n        container.Register(Component.For(typeof(INotificationHandler<>), typeof(ConstrainedPingedHandler<>)).NamedAutomatically(\"ConstrainedPingedHandler\"));\n\n        var mediator = container.Resolve<IMediator>();\n\n        return mediator;\n    }\n\n    private static object ResolveRequestExceptionHandler(IKernel k, Type type, Type service, object resolvedType, Type[] genericArguments)\n    {\n        if (service == null\n        || genericArguments == null\n        || !service.IsInterface\n        || !service.IsGenericType\n        || !service.IsConstructedGenericType\n        || !(service.GetGenericTypeDefinition()\n        ?.IsAssignableTo(typeof(IRequestExceptionHandler<,,>)) ?? false)\n        || genericArguments.Length != 3)\n        {\n            return resolvedType;\n        }\n\n        var serviceFactory = k.Resolve<ServiceFactory>();\n        var baseRequestType = genericArguments[0].BaseType;\n        var response = genericArguments[1];\n        var exceptionType = genericArguments[2];\n\n        // Check if the base request type is valid\n        if (baseRequestType == null\n        || !baseRequestType.IsClass\n        || baseRequestType == typeof(object)\n        || ((!baseRequestType.GetInterfaces()\n            ?.Any(i => i.IsAssignableFrom(typeof(IRequest<>)))) ?? true))\n        {\n            return resolvedType;\n        }\n\n        var exceptionHandlerInterfaceType = typeof(IRequestExceptionHandler<,,>).MakeGenericType(baseRequestType, response, exceptionType);\n        var enumerableExceptionHandlerInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionHandlerInterfaceType);\n        Array resultArray = CreateArraysOutOfResolvedTypeAndEnumerableInterfaceTypes(type, resolvedType, serviceFactory, enumerableExceptionHandlerInterfaceType);\n\n        return resultArray;\n    }\n\n    private static object ResolveRequestExceptionAction(IKernel k, Type type, Type service, object resolvedType, Type[] genericArguments)\n    {\n        if (service == null\n        || genericArguments == null\n        || !service.IsInterface\n        || !service.IsGenericType\n        || !service.IsConstructedGenericType\n        || !(service.GetGenericTypeDefinition()\n        ?.IsAssignableTo(typeof(IRequestExceptionAction<,>)) ?? false)\n        || genericArguments.Length != 2)\n        {\n            return resolvedType;\n        }\n\n        var serviceFactory = k.Resolve<ServiceFactory>();\n        var baseRequestType = genericArguments[0].BaseType;\n        var exceptionType = genericArguments[1];\n\n        // Check if the base request type is valid\n        if (baseRequestType == null\n        || !baseRequestType.IsClass\n        || baseRequestType == typeof(object)\n        || ((!baseRequestType.GetInterfaces()\n            ?.Any(i => i.IsAssignableFrom(typeof(IRequest<>)))) ?? true))\n        {\n            return resolvedType;\n        }\n\n        var exceptionHandlerInterfaceType = typeof(IRequestExceptionAction<,>).MakeGenericType(baseRequestType, exceptionType);\n        var enumerableExceptionHandlerInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionHandlerInterfaceType);\n        Array resultArray = CreateArraysOutOfResolvedTypeAndEnumerableInterfaceTypes(type, resolvedType, serviceFactory, enumerableExceptionHandlerInterfaceType);\n\n        return resultArray;\n    }\n\n    private static Array CreateArraysOutOfResolvedTypeAndEnumerableInterfaceTypes(Type type, object resolvedType, ServiceFactory serviceFactory, Type enumerableExceptionHandlerInterfaceType)\n    {\n        var firstArray = serviceFactory.Invoke(enumerableExceptionHandlerInterfaceType) as Array;\n        Debug.Assert(firstArray != null, $\"Array '{nameof(firstArray)}' should not be null because this method calls ResolveAll when a {typeof(IEnumerable<>).FullName} \" +\n            $\"is passed as argument in argument named '{nameof(type)}'\");\n\n        var secondArray = resolvedType is Array ? resolvedType as Array : new[] { resolvedType };\n        Debug.Assert(secondArray != null, $\"Array '{nameof(secondArray)}' should not be null because '{nameof(resolvedType)}' is an array or created as an array\");\n\n        var resultArray = Array.CreateInstance(typeof(object), firstArray.Length + secondArray.Length);\n        Array.Copy(firstArray, resultArray, firstArray.Length);\n        Array.Copy(secondArray, 0, resultArray, firstArray.Length, secondArray.Length);\n        return resultArray;\n    }\n}\n"
  },
  {
    "path": "src/MediatR/Entities/OpenBehavior.cs",
    "content": "using Microsoft.Extensions.DependencyInjection;\nusing System;\nusing System.Linq;\n\nnamespace MediatR.Entities;\n/// <summary>\n/// Represents a registration entity for pipeline behaviors with a specified service lifetime.\n/// </summary>\npublic class OpenBehavior\n{\n    /// <summary>\n    /// Initializes a new instance of the <see cref=\"OpenBehavior\"/> class.\n    /// </summary>\n    /// <param name=\"openBehaviorType\">The type of the pipeline behavior to register.</param>\n    /// <param name=\"serviceLifetime\">The lifetime of the registered service. Defaults to Transient.</param>\n    /// <exception cref=\"InvalidOperationException\">Thrown if the specified type does not implement IPipelineBehavior.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown if <paramref name=\"openBehaviorType\"/> is null.</exception>\n    public OpenBehavior(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\n    {\n        ValidatePipelineBehaviorType(openBehaviorType);\n        OpenBehaviorType = openBehaviorType;\n        ServiceLifetime = serviceLifetime;\n    }\n\n    /// <summary>\n    /// The type of the open behavior.\n    /// </summary>\n    public Type OpenBehaviorType { get; }\n\n    /// <summary>\n    /// The service lifetime of the open behavior.\n    /// </summary>\n    public ServiceLifetime ServiceLifetime { get; }\n\n    /// <summary>\n    /// Validates whether the specified type implements the <see cref=\"IPipelineBehavior{TRequest, TResponse}\"/> interface.\n    /// </summary>\n    /// <param name=\"openBehaviorType\">The type to validate.</param>\n    /// <exception cref=\"InvalidOperationException\">Thrown if the type does not implement <see cref=\"IPipelineBehavior{TRequest, TResponse}\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown if <paramref name=\"openBehaviorType\"/> is null.</exception>\n    private static void ValidatePipelineBehaviorType(Type openBehaviorType)\n    {\n        if (openBehaviorType == null) throw new ArgumentNullException($\"Open behavior type can not be null.\");\n\n        bool isPipelineBehavior = openBehaviorType.GetInterfaces()\n            .Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPipelineBehavior<,>));\n\n        if (!isPipelineBehavior)\n        {\n            throw new InvalidOperationException($\"The type \\\"{openBehaviorType.Name}\\\" must implement IPipelineBehavior<,> interface.\");\n        }\n    }\n}"
  },
  {
    "path": "src/MediatR/IMediator.cs",
    "content": "namespace MediatR;\n\n/// <summary>\n/// Defines a mediator to encapsulate request/response and publishing interaction patterns\n/// </summary>\npublic interface IMediator : ISender, IPublisher\n{\n}"
  },
  {
    "path": "src/MediatR/INotificationHandler.cs",
    "content": "using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR;\n\n/// <summary>\n/// Defines a handler for a notification\n/// </summary>\n/// <typeparam name=\"TNotification\">The type of notification being handled</typeparam>\npublic interface INotificationHandler<in TNotification>\n    where TNotification : INotification\n{\n    /// <summary>\n    /// Handles a notification\n    /// </summary>\n    /// <param name=\"notification\">The notification</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    Task Handle(TNotification notification, CancellationToken cancellationToken);\n}\n\n/// <summary>\n/// Wrapper class for a synchronous notification handler\n/// </summary>\n/// <typeparam name=\"TNotification\">The notification type</typeparam>\npublic abstract class NotificationHandler<TNotification> : INotificationHandler<TNotification>\n    where TNotification : INotification\n{\n    Task INotificationHandler<TNotification>.Handle(TNotification notification, CancellationToken cancellationToken)\n    {\n        Handle(notification);\n\n        return Task.CompletedTask;\n    }\n\n    /// <summary>\n    /// Override in a derived class for the handler logic\n    /// </summary>\n    /// <param name=\"notification\">Notification</param>\n    protected abstract void Handle(TNotification notification);\n}"
  },
  {
    "path": "src/MediatR/INotificationPublisher.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Threading.Tasks;\nusing System.Threading;\n\nnamespace MediatR;\n\npublic interface INotificationPublisher\n{\n    Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification,\n        CancellationToken cancellationToken);\n}"
  },
  {
    "path": "src/MediatR/IPipelineBehavior.cs",
    "content": "\nnamespace MediatR;\n\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Represents an async continuation for the next task to execute in the pipeline\n/// </summary>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\n/// <returns>Awaitable task returning a <typeparamref name=\"TResponse\"/></returns>\npublic delegate Task<TResponse> RequestHandlerDelegate<TResponse>(CancellationToken t = default);\n\n/// <summary>\n/// Pipeline behavior to surround the inner handler.\n/// Implementations add additional behavior and await the next delegate.\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic interface IPipelineBehavior<in TRequest, TResponse> where TRequest : notnull\n{\n    /// <summary>\n    /// Pipeline handler. Perform any additional behavior and await the <paramref name=\"next\"/> delegate as necessary\n    /// </summary>\n    /// <param name=\"request\">Incoming request</param>\n    /// <param name=\"next\">Awaitable delegate for the next action in the pipeline. Eventually this delegate represents the handler.</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>Awaitable task returning the <typeparamref name=\"TResponse\"/></returns>\n    Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken);\n}"
  },
  {
    "path": "src/MediatR/IPublisher.cs",
    "content": "﻿using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR;\n\n/// <summary>\n/// Publish a notification or event through the mediator pipeline to be handled by multiple handlers.\n/// </summary>\npublic interface IPublisher\n{\n    /// <summary>\n    /// Asynchronously send a notification to multiple handlers\n    /// </summary>\n    /// <param name=\"notification\">Notification object</param>\n    /// <param name=\"cancellationToken\">Optional cancellation token</param>\n    /// <returns>A task that represents the publish operation.</returns>\n    Task Publish(object notification, CancellationToken cancellationToken = default);\n\n    /// <summary>\n    /// Asynchronously send a notification to multiple handlers\n    /// </summary>\n    /// <param name=\"notification\">Notification object</param>\n    /// <param name=\"cancellationToken\">Optional cancellation token</param>\n    /// <returns>A task that represents the publish operation.</returns>\n    Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default)\n        where TNotification : INotification;\n}"
  },
  {
    "path": "src/MediatR/IRequestHandler.cs",
    "content": "using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR;\n\n/// <summary>\n/// Defines a handler for a request\n/// </summary>\n/// <typeparam name=\"TRequest\">The type of request being handled</typeparam>\n/// <typeparam name=\"TResponse\">The type of response from the handler</typeparam>\npublic interface IRequestHandler<in TRequest, TResponse>\n    where TRequest : IRequest<TResponse>\n{\n    /// <summary>\n    /// Handles a request\n    /// </summary>\n    /// <param name=\"request\">The request</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>Response from the request</returns>\n    Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken);\n}\n\n/// <summary>\n/// Defines a handler for a request with a void response.\n/// </summary>\n/// <typeparam name=\"TRequest\">The type of request being handled</typeparam>\npublic interface IRequestHandler<in TRequest>\n    where TRequest : IRequest\n{\n    /// <summary>\n    /// Handles a request\n    /// </summary>\n    /// <param name=\"request\">The request</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>Response from the request</returns>\n    Task Handle(TRequest request, CancellationToken cancellationToken);\n}\n"
  },
  {
    "path": "src/MediatR/ISender.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR;\n\n/// <summary>\n/// Send a request through the mediator pipeline to be handled by a single handler.\n/// </summary>\npublic interface ISender\n{\n    /// <summary>\n    /// Asynchronously send a request to a single handler\n    /// </summary>\n    /// <typeparam name=\"TResponse\">Response type</typeparam>\n    /// <param name=\"request\">Request object</param>\n    /// <param name=\"cancellationToken\">Optional cancellation token</param>\n    /// <returns>A task that represents the send operation. The task result contains the handler response</returns>\n    Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default);\n\n    /// <summary>\n    /// Asynchronously send a request to a single handler with no response\n    /// </summary>\n    /// <param name=\"request\">Request object</param>\n    /// <param name=\"cancellationToken\">Optional cancellation token</param>\n    /// <returns>A task that represents the send operation.</returns>\n    Task Send<TRequest>(TRequest request, CancellationToken cancellationToken = default)\n        where TRequest : IRequest;\n\n    /// <summary>\n    /// Asynchronously send an object request to a single handler via dynamic dispatch\n    /// </summary>\n    /// <param name=\"request\">Request object</param>\n    /// <param name=\"cancellationToken\">Optional cancellation token</param>\n    /// <returns>A task that represents the send operation. The task result contains the type erased handler response</returns>\n    Task<object?> Send(object request, CancellationToken cancellationToken = default);\n\n    /// <summary>\n    /// Create a stream via a single stream handler\n    /// </summary>\n    /// <typeparam name=\"TResponse\"></typeparam>\n    /// <param name=\"request\"></param>\n    /// <param name=\"cancellationToken\"></param>\n    /// <returns></returns>\n    IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamRequest<TResponse> request, CancellationToken cancellationToken = default);\n\n    /// <summary>\n    /// Create a stream via an object request to a stream handler\n    /// </summary>\n    /// <param name=\"request\"></param>\n    /// <param name=\"cancellationToken\"></param>\n    /// <returns></returns>\n    IAsyncEnumerable<object?> CreateStream(object request, CancellationToken cancellationToken = default);\n}"
  },
  {
    "path": "src/MediatR/IStreamPipelineBehavior.cs",
    "content": "﻿\nnamespace MediatR;\n\nusing System.Collections.Generic;\nusing System.Threading;\n\n/// <summary>\n/// Represents an async enumerable continuation for the next task to execute in the pipeline\n/// </summary>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\n/// <returns>Async Enumerable returning a <typeparamref name=\"TResponse\"/></returns>\npublic delegate IAsyncEnumerable<TResponse> StreamHandlerDelegate<out TResponse>();\n\n/// <summary>\n/// Stream Pipeline behavior to surround the inner handler.\n/// Implementations add additional behavior and await the next delegate.\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic interface IStreamPipelineBehavior<in TRequest, TResponse> where TRequest : notnull\n{\n    /// <summary>\n    /// Stream Pipeline handler. Perform any additional behavior and iterate the <paramref name=\"next\"/> delegate as necessary\n    /// </summary>\n    /// <param name=\"request\">Incoming request</param>\n    /// <param name=\"next\">Awaitable delegate for the next action in the pipeline. Eventually this delegate represents the handler.</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>Awaitable task returning the <typeparamref name=\"TResponse\"/></returns>\n    IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, CancellationToken cancellationToken);\n}"
  },
  {
    "path": "src/MediatR/IStreamRequestHandler.cs",
    "content": "using System.Collections.Generic;\nusing System.Threading;\n\nnamespace MediatR;\n\n/// <summary>\n/// Defines a handler for a stream request using IAsyncEnumerable as return type.\n/// </summary>\n/// <typeparam name=\"TRequest\">The type of request being handled</typeparam>\n/// <typeparam name=\"TResponse\">The type of response from the handler</typeparam>\npublic interface IStreamRequestHandler<in TRequest, out TResponse>\n    where TRequest : IStreamRequest<TResponse>\n{\n    /// <summary>\n    /// Handles a stream request with IAsyncEnumerable as return type.\n    /// </summary>\n    /// <param name=\"request\">The request</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>Response from the request</returns>\n    IAsyncEnumerable<TResponse> Handle(TRequest request, CancellationToken cancellationToken);\n}\n"
  },
  {
    "path": "src/MediatR/Internal/HandlersOrderer.cs",
    "content": "namespace MediatR.Internal;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\n\ninternal static class HandlersOrderer\n{\n    public static IList<object> Prioritize<TRequest>(IList<object> handlers, TRequest request)\n        where TRequest : notnull\n    {\n        if (handlers.Count < 2)\n        {\n            return handlers;\n        }\n\n        var requestObjectDetails = new ObjectDetails(request);\n        var handlerObjectsDetails = handlers.Select(static s => new ObjectDetails(s)).ToList();\n\n        var uniqueHandlers = RemoveOverridden(handlerObjectsDetails).ToArray();\n        Array.Sort(uniqueHandlers, requestObjectDetails);\n\n        return uniqueHandlers.Select(static s => s.Value).ToList();\n    }\n\n    private static IEnumerable<ObjectDetails> RemoveOverridden(IList<ObjectDetails> handlersData)\n    {\n        for (var i = 0; i < handlersData.Count - 1; i++)\n        {\n            for (var j = i + 1; j < handlersData.Count; j++)\n            {\n                if (handlersData[i].IsOverridden || handlersData[j].IsOverridden)\n                {\n                    continue;\n                }\n\n                if (handlersData[i].Type.IsAssignableFrom(handlersData[j].Type))\n                {\n                    handlersData[i].IsOverridden = true;\n                }\n                else if (handlersData[j].Type.IsAssignableFrom(handlersData[i].Type))\n                {\n                    handlersData[j].IsOverridden = true;\n                }\n            }\n        }\n\n        return handlersData.Where(static w => !w.IsOverridden);\n    }\n}"
  },
  {
    "path": "src/MediatR/Internal/ObjectDetails.cs",
    "content": "using System;\nusing System.Collections.Generic;\n\nnamespace MediatR.Internal;\n\ninternal class ObjectDetails : IComparer<ObjectDetails>\n{\n    public string Name { get; }\n\n    public string? AssemblyName { get; }\n\n    public string? Location { get; }\n\n    public object Value { get; }\n\n    public Type Type { get; }\n\n    public bool IsOverridden { get; set; }\n\n    public ObjectDetails(object value)\n    {\n        Value = value;\n        Type = Value.GetType();\n        var exceptionHandlerType = value.GetType();\n\n        Name = exceptionHandlerType.Name;\n        AssemblyName = exceptionHandlerType.Assembly.GetName().Name;\n        Location = exceptionHandlerType.Namespace?.Replace($\"{AssemblyName}.\", string.Empty);\n    }\n\n    public int Compare(ObjectDetails? x, ObjectDetails? y)\n    {\n        if (x == null)\n        {\n            return 1;\n        }\n\n        if (y == null)\n        {\n            return -1;\n        }\n\n        return CompareByAssembly(x, y) ?? CompareByNamespace(x, y) ?? CompareByLocation(x, y);\n    }\n\n    /// <summary>\n    /// Compare two objects according to current assembly\n    /// </summary>\n    /// <param name=\"x\">First object to compare</param>\n    /// <param name=\"y\">Second object to compare</param>\n    /// <returns>\n    /// An object has a higher priority if it belongs to the current assembly and the other is not;\n    /// If none of the objects belong to the current assembly, they can be considered equal;\n    /// If both objects belong to the current assembly, they can't be compared only by this criterion.\n    /// </returns>\n    private int? CompareByAssembly(ObjectDetails x, ObjectDetails y)\n    {\n        if (x.AssemblyName == AssemblyName && y.AssemblyName != AssemblyName)\n        {\n            return -1;\n        }\n\n        if (x.AssemblyName != AssemblyName && y.AssemblyName == AssemblyName)\n        {\n            return 1;\n        }\n        if (x.AssemblyName != AssemblyName && y.AssemblyName != AssemblyName)\n        {\n            return 0;\n        }\n\n        return null;\n    }\n\n    /// <summary>\n    /// Compare two objects according to current namespace\n    /// </summary>\n    /// <param name=\"x\">First object to compare</param>\n    /// <param name=\"y\">Second object to compare</param>\n    /// <returns>\n    /// An object has a higher priority if it belongs to the current/child namespace and the other is not;\n    /// If both objects belong to the current/child namespace, they can be considered equal;\n    /// If none of the objects belong to the current/child namespace, they can't be compared by this criterion.\n    /// </returns>\n    private int? CompareByNamespace(ObjectDetails x, ObjectDetails y)\n    {\n        if (Location is null || x.Location is null || y.Location is null)\n        {\n            return 0;\n        }\n\n        if (x.Location.StartsWith(Location, StringComparison.Ordinal) && !y.Location.StartsWith(Location, StringComparison.Ordinal))\n        {\n            return -1;\n        }\n\n        if (!x.Location.StartsWith(Location, StringComparison.Ordinal) && y.Location.StartsWith(Location, StringComparison.Ordinal))\n        {\n            return 1;\n        }\n        if (x.Location.StartsWith(Location, StringComparison.Ordinal) && y.Location.StartsWith(Location, StringComparison.Ordinal))\n        {\n            return 0;\n        }\n\n        return null;\n    }\n\n    /// <summary>\n    /// Compare two objects according to location in the assembly\n    /// </summary>\n    /// <param name=\"x\">First object to compare</param>\n    /// <param name=\"y\">Second object to compare</param>\n    /// <returns>\n    /// An object has a higher priority if it location is part of the current location and the other is not;\n    /// If both objects are part of the current location, the closest has higher priority;\n    /// If none of the objects are part of the current location, they can be considered equal.\n    /// </returns>\n    private int CompareByLocation(ObjectDetails x, ObjectDetails y)\n    {\n        if (Location is null || x.Location is null || y.Location is null)\n        {\n            return 0;\n        }\n\n        if (Location.StartsWith(x.Location, StringComparison.Ordinal) && !Location.StartsWith(y.Location, StringComparison.Ordinal))\n        {\n            return -1;\n        }\n\n        if (!Location.StartsWith(x.Location, StringComparison.Ordinal) && Location.StartsWith(y.Location, StringComparison.Ordinal))\n        {\n            return 1;\n        }\n        if (x.Location.Length > y.Location.Length)\n        {\n            return -1;\n        }\n        if (x.Location.Length < y.Location.Length)\n        {\n            return 1;\n        }\n        return 0;\n    }\n}"
  },
  {
    "path": "src/MediatR/Licensing/BuildInfo.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Reflection;\n\nnamespace MediatR.Licensing;\n\ninternal static class BuildInfo\n{\n    public static DateTimeOffset? BuildDate { get; } = GetBuildDate();\n\n    private static DateTimeOffset? GetBuildDate()\n    {\n        var assembly = typeof(BuildInfo).Assembly;\n\n        var buildDateAttribute = assembly\n            .GetCustomAttributes<AssemblyMetadataAttribute>()\n            .FirstOrDefault(a => a.Key == \"BuildDateUtc\");\n\n        if (buildDateAttribute?.Value != null &&\n            DateTimeOffset.TryParse(buildDateAttribute.Value, out var buildDate))\n        {\n            return buildDate;\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/MediatR/Licensing/Edition.cs",
    "content": "namespace MediatR.Licensing;\n\ninternal enum Edition\n{\n    Community = 0,\n    Standard = 1,\n    Professional = 2,\n    Enterprise = 3\n}"
  },
  {
    "path": "src/MediatR/Licensing/License.cs",
    "content": "using System;\nusing System.Diagnostics.CodeAnalysis;\nusing System.Security.Claims;\n\nnamespace MediatR.Licensing;\n\ninternal class License\n{\n    internal License(params Claim[] claims) : this(new ClaimsPrincipal(new ClaimsIdentity(claims)))\n    {\n        \n    }\n    \n    public License(ClaimsPrincipal claims)\n    {\n        if (Guid.TryParse(claims.FindFirst(\"account_id\")?.Value, out var accountId))\n        {\n            AccountId = accountId;\n        }\n\n        CustomerId = claims.FindFirst(\"customer_id\")?.Value;\n        SubscriptionId = claims.FindFirst(\"sub_id\")?.Value;\n\n        if (long.TryParse(claims.FindFirst(\"iat\")?.Value, out var iat))\n        {\n            var startedAt = DateTimeOffset.FromUnixTimeSeconds(iat);\n            StartDate = startedAt;\n        }\n        \n        if (long.TryParse(claims.FindFirst(\"exp\")?.Value, out var exp))\n        {\n            var expiredAt = DateTimeOffset.FromUnixTimeSeconds(exp);\n            ExpirationDate = expiredAt;\n        }\n\n        if (Enum.TryParse<Edition>(claims.FindFirst(\"edition\")?.Value, out var edition))\n        { \n            Edition = edition;\n        }\n\n        if (Enum.TryParse<ProductType>(claims.FindFirst(\"type\")?.Value, out var productType))\n        {\n            ProductType = productType;\n        }\n\n        var perpetualValue = claims.FindFirst(\"perpetual\")?.Value;\n        IsPerpetual = perpetualValue?.ToLowerInvariant() is \"true\" or \"1\";\n\n        IsConfigured = AccountId != null\n                       && CustomerId != null\n                       && SubscriptionId != null\n                       && StartDate != null\n                       && ExpirationDate != null\n                       && Edition != null\n                       && ProductType != null;\n    }\n\n    public Guid? AccountId { get; }\n    public string? CustomerId { get; }\n    public string? SubscriptionId { get; }\n    public DateTimeOffset? StartDate { get; }\n    public DateTimeOffset? ExpirationDate { get; }\n    public Edition? Edition { get; }\n    public ProductType? ProductType { get; }\n    public bool IsPerpetual { get; }\n\n    public bool IsConfigured { get; }\n}"
  },
  {
    "path": "src/MediatR/Licensing/LicenseAccessor.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing System.Security.Claims;\nusing System.Security.Cryptography;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.IdentityModel.JsonWebTokens;\nusing Microsoft.IdentityModel.Tokens;\nusing Convert = System.Convert;\n\nnamespace MediatR.Licensing;\n\ninternal class LicenseAccessor\n{\n    private readonly MediatRServiceConfiguration? _configuration;\n    private readonly ILogger _logger;\n\n    public LicenseAccessor(MediatRServiceConfiguration configuration, ILoggerFactory loggerFactory)\n    {\n        _configuration = configuration;\n        _logger = loggerFactory.CreateLogger(\"LuckyPennySoftware.MediatR.License\");\n    }   \n    \n    public LicenseAccessor(ILoggerFactory loggerFactory)\n    {\n        _logger = loggerFactory.CreateLogger(\"LuckyPennySoftware.MediatR.License\");\n    }\n    \n    private License? _license;\n    private readonly object _lock = new();\n\n    public License Current => _license ??= Initialize();\n\n    private License Initialize()\n    {\n        lock (_lock)\n        {\n            if (_license != null)\n            {\n                return _license;\n            }\n\n            var key = _configuration?.LicenseKey\n                      ?? Mediator.LicenseKey\n                      ?? null;\n            \n            if (key == null)\n            {\n                return new License();\n            }\n\n            var licenseClaims = ValidateKey(key);\n            return licenseClaims.Any() \n                ? new License(new ClaimsPrincipal(new ClaimsIdentity(licenseClaims))) \n                : new License();\n        }\n    }\n    \n    private Claim[] ValidateKey(string licenseKey)\n    {\n        var handler = new JsonWebTokenHandler();\n\n        var rsa = new RSAParameters\n        {\n            Exponent = Convert.FromBase64String(\"AQAB\"),\n            Modulus = Convert.FromBase64String(\n                \"2LTtdJV2b0mYoRqChRCfcqnbpKvsiCcDYwJ+qPtvQXWXozOhGo02/V0SWMFBdbZHUzpEytIiEcojo7Vbq5mQmt4lg92auyPKsWq6qSmCVZCUuL/kpYqLCit4yUC0YqZfw4H9zLf1yAIOgyXQf1x6g+kscDo1pWAniSl9a9l/LXRVEnGz+OfeUrN/5gzpracGUY6phx6T09UCRuzi4YqqO4VJzL877W0jCW2Q7jMzHxOK04VSjNc22CADuCd34mrFs23R0vVm1DVLYtPGD76/rGOcxO6vmRc7ydBAvt1IoUsrY0vQ2rahp51YPxqqhKPd8nNOomHWblCCA7YUeV3C1Q==\")\n        };;\n\n        var key = new RsaSecurityKey(rsa)\n        {\n            KeyId = \"LuckyPennySoftwareLicenseKey/bbb13acb59904d89b4cb1c85f088ccf9\"\n        };\n\n        var parms = new TokenValidationParameters\n        {\n            ValidIssuer = \"https://luckypennysoftware.com\",\n            ValidAudience = \"LuckyPennySoftware\",\n            IssuerSigningKey = key,\n            ValidateLifetime = false\n        };\n\n        var validateResult = Task.Run(() => handler.ValidateTokenAsync(licenseKey, parms)).GetAwaiter().GetResult();\n        if (!validateResult.IsValid)\n        {\n            _logger.LogCritical(validateResult.Exception, \"Error validating the Lucky Penny software license key\");\n        }\n\n        return validateResult.ClaimsIdentity?.Claims.ToArray() ?? Array.Empty<Claim>();\n    }\n\n}"
  },
  {
    "path": "src/MediatR/Licensing/LicenseValidator.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing Microsoft.Extensions.Logging;\n\nnamespace MediatR.Licensing;\n\ninternal class LicenseValidator\n{\n    private readonly ILogger _logger;\n    private readonly DateTimeOffset? _buildDate;\n\n    public LicenseValidator(ILoggerFactory loggerFactory) : this(loggerFactory, BuildInfo.BuildDate)\n    {\n    }\n\n    public LicenseValidator(ILoggerFactory loggerFactory, DateTimeOffset? buildDate)\n    {\n        _logger = loggerFactory.CreateLogger(\"LuckyPennySoftware.MediatR.License\");\n        _buildDate = buildDate;\n    }\n\n    public void Validate(License license)\n    {\n        var errors = new List<string>();\n\n        if (license is not { IsConfigured: true })\n        {\n            var message = \"You do not have a valid license key for the Lucky Penny software MediatR. \" +\n                          \"This is allowed for development and testing scenarios. \" +\n                          \"If you are running in production you are required to have a licensed version. \" +\n                          \"Please visit https://luckypennysoftware.com to obtain a valid license.\";\n\n            _logger.LogWarning(message);\n            return;\n        }\n\n        _logger.LogDebug(\"The Lucky Penny license key details: {license}\", license);\n\n        var diff = DateTime.UtcNow.Date.Subtract(license.ExpirationDate!.Value.Date).TotalDays;\n        if (diff > 0)\n        {\n            // If perpetual, check if build date is before expiration\n            if (license.IsPerpetual && _buildDate.HasValue)\n            {\n                var buildDateDiff = _buildDate.Value.Date.Subtract(license.ExpirationDate.Value.Date).TotalDays;\n                if (buildDateDiff <= 0)\n                {\n                    _logger.LogInformation(\n                        \"Your license for the Lucky Penny software MediatR expired {expiredDaysAgo} days ago, but perpetual licensing is active because the build date ({buildDate:O}) is before the license expiration date ({licenseExpiration:O}).\",\n                        diff, _buildDate, license.ExpirationDate);\n                    // Don't add to errors - perpetual fallback applies\n                }\n                else\n                {\n                    errors.Add($\"Your license for the Lucky Penny software MediatR expired {diff} days ago.\");\n                }\n            }\n            else\n            {\n                if (license.IsPerpetual)\n                {\n                    _logger.LogWarning(\n                        \"Your license for the Lucky Penny software MediatR has perpetual licensing enabled, but the build date could not be determined. Perpetual licensing cannot be applied. Please ensure the assembly metadata is correctly embedded at build time.\");\n                }\n                errors.Add($\"Your license for the Lucky Penny software MediatR expired {diff} days ago.\");\n            }\n        }\n\n        if (license.ProductType!.Value != ProductType.MediatR\n            && license.ProductType.Value != ProductType.Bundle)\n        {\n            errors.Add(\"Your Lucky Penny software license does not include MediatR.\");\n        }\n\n        if (errors.Count > 0)\n        {\n            foreach (var err in errors)\n            {\n                _logger.LogError(err);\n            }\n\n            _logger.LogError(\n                \"Please visit https://luckypennysoftware.com to obtain a valid license for the Lucky Penny software MediatR.\");\n        }\n        else\n        {\n            _logger.LogInformation(\"You have a valid license key for the Lucky Penny software {type} {edition} edition. The license expires on {licenseExpiration}.\",\n                license.ProductType,\n                license.Edition,\n                license.ExpirationDate);\n        }\n    }\n}"
  },
  {
    "path": "src/MediatR/Licensing/ProductType.cs",
    "content": "namespace MediatR.Licensing;\n\ninternal enum ProductType\n{\n    AutoMapper = 0,\n    MediatR = 1,\n    Bundle = 2\n}"
  },
  {
    "path": "src/MediatR/MediatR.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Authors>Jimmy Bogard</Authors>\n    <Description>Simple, unambitious mediator implementation in .NET</Description>\n    <Copyright>Copyright Jimmy Bogard</Copyright>\n    <TargetFrameworks>netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>\n    <Nullable>enable</Nullable>\n    <Features>strict</Features>\n    <PackageTags>mediator;request;response;queries;commands;notifications</PackageTags>\n    <SignAssembly>true</SignAssembly>\n    <AssemblyOriginatorKeyFile>..\\..\\MediatR.snk</AssemblyOriginatorKeyFile>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageIcon>gradient_128x128.png</PackageIcon>\n    <PackageReadmeFile>README.md</PackageReadmeFile>\n    <PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>\n    <PackageLicenseFile>LICENSE.md</PackageLicenseFile>\n    <PackageProjectUrl>https://mediatr.io</PackageProjectUrl>\n    <MinVerTagPrefix>v</MinVerTagPrefix>\n    <PublishRepositoryUrl>true</PublishRepositoryUrl>\n    <IncludeSymbols>true</IncludeSymbols>\n    <SymbolPackageFormat>snupkg</SymbolPackageFormat>\n    <EmbedUntrackedSources>true</EmbedUntrackedSources>\n    <Deterministic>true</Deterministic>\n    <ContinuousIntegrationBuild Condition=\"'$(GITHUB_ACTIONS)' == 'true'\">true</ContinuousIntegrationBuild>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\" '$(IsWindows)' == 'true' \">\n    <TargetFrameworks>$(TargetFrameworks);net462</TargetFrameworks>\n  </PropertyGroup>\n\n  <Target Name=\"EmbedBuildDate\" BeforeTargets=\"CoreCompile\">\n    <Exec Command=\"git log -1 --format=%25cI\" ConsoleToMSBuild=\"true\" IgnoreExitCode=\"true\">\n      <Output TaskParameter=\"ConsoleOutput\" PropertyName=\"BuildDateUtc\" />\n    </Exec>\n    <PropertyGroup>\n      <BuildDateUtc Condition=\"'$(BuildDateUtc)' == ''\">$([System.DateTime]::UtcNow.ToString(\"O\"))</BuildDateUtc>\n    </PropertyGroup>\n    <WriteLinesToFile File=\"$(IntermediateOutputPath)BuildDateGenerated.cs\" Lines=\"[assembly: System.Reflection.AssemblyMetadata(&quot;BuildDateUtc&quot;, &quot;$(BuildDateUtc)&quot;)]\" Overwrite=\"true\" />\n    <ItemGroup>\n      <Compile Include=\"$(IntermediateOutputPath)BuildDateGenerated.cs\" />\n    </ItemGroup>\n  </Target>\n\n  <ItemGroup>\n    <None Include=\"..\\..\\assets\\logo\\gradient_128x128.png\" Pack=\"true\" PackagePath=\"\" />\n    <None Include=\"..\\..\\LICENSE.md\" Pack=\"true\" PackagePath=\"\" />\n    <None Include=\"..\\..\\README.md\" Pack=\"true\" PackagePath=\"\\\" />\n  </ItemGroup>\n  \n  <ItemGroup>\n    <AssemblyAttribute Include=\"System.Runtime.CompilerServices.InternalsVisibleToAttribute\">\n      <_Parameter1>MediatR.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010091986edd141861f402457659cb82b56cf6a0d60b3bd2e5aa4ea73d88afa929d278462d6c4c0e2ecbce21948c15514a310a82e6b2e6beaab6cb14230a03bc026609be59f938423f2490fa0033ae87a982fb4950db77d1a4635e14f7727161e93e5511de766ed8e515efd801464b7820a27fca30a32161485824e442cc5ffecfbe</_Parameter1>\n    </AssemblyAttribute>\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"IsExternalInit\" Version=\"1.0.3\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"MediatR.Contracts\" Version=\"[2.0.1, 3.0.0)\" />\n    <PackageReference Include=\"Microsoft.Bcl.AsyncInterfaces\" Version=\"[10.0.0, )\" Condition=\"'$(TargetFramework)' == 'netstandard2.0'\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection.Abstractions\" Version=\"[10.0.0, )\" />\n    <PackageReference Include=\"Microsoft.Extensions.Logging.Abstractions\" Version=\"[10.0.0, )\" />\n    <PackageReference Include=\"Microsoft.IdentityModel.JsonWebTokens\" Version=\"[8.14.0, )\" />\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"8.0.0\" PrivateAssets=\"All\" />\n    <PackageReference Include=\"MinVer\" Version=\"6.0.0\" PrivateAssets=\"All\" />\n  </ItemGroup>\n  \n</Project>\n"
  },
  {
    "path": "src/MediatR/Mediator.cs",
    "content": "using MediatR.NotificationPublishers;\r\nusing Microsoft.Extensions.DependencyInjection;\r\n\r\nnamespace MediatR;\r\n\r\nusing System;\r\nusing System.Collections.Concurrent;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\nusing Wrappers;\r\n\r\n/// <summary>\r\n/// Default mediator implementation relying on single- and multi instance delegates for resolving handlers.\r\n/// </summary>\r\npublic class Mediator : IMediator\r\n{\r\n    private readonly IServiceProvider _serviceProvider;\r\n    private readonly INotificationPublisher _publisher;\r\n    private static readonly ConcurrentDictionary<Type, RequestHandlerBase> _requestHandlers = new();\r\n    private static readonly ConcurrentDictionary<Type, NotificationHandlerWrapper> _notificationHandlers = new();\r\n    private static readonly ConcurrentDictionary<Type, StreamRequestHandlerBase> _streamRequestHandlers = new();\r\n\r\n    /// <summary>\r\n    /// Initializes a new instance of the <see cref=\"Mediator\"/> class.\r\n    /// </summary>\r\n    /// <param name=\"serviceProvider\">Service provider. Can be a scoped or root provider</param>\r\n    public Mediator(IServiceProvider serviceProvider) \r\n        : this(serviceProvider, new ForeachAwaitPublisher()) { }\r\n\r\n    /// <summary>\r\n    /// Initializes a new instance of the <see cref=\"Mediator\"/> class.\r\n    /// </summary>\r\n    /// <param name=\"serviceProvider\">Service provider. Can be a scoped or root provider</param>\r\n    /// <param name=\"publisher\">Notification publisher. Defaults to <see cref=\"ForeachAwaitPublisher\"/>.</param>\r\n    public Mediator(IServiceProvider serviceProvider, INotificationPublisher publisher)\r\n    {\r\n        _serviceProvider = serviceProvider;\r\n        _publisher = publisher;\r\n        \r\n        _serviceProvider.CheckLicense();\r\n    }\r\n\r\n    /// <summary>\r\n    /// Gets or sets the license key. You can find your license key in your <a href=\"https://luckypennysoftware.com/account\">account</a>.\r\n    /// </summary>\r\n    public static string? LicenseKey { get; set; }\r\n\r\n    public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default)\r\n    {\r\n        if (request == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(request));\r\n        }\r\n\r\n        var handler = (RequestHandlerWrapper<TResponse>)_requestHandlers.GetOrAdd(request.GetType(), static requestType =>\r\n        {\r\n            var wrapperType = typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse));\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper type for {requestType}\");\r\n            return (RequestHandlerBase)wrapper;\r\n        });\r\n\r\n        return handler.Handle(request, _serviceProvider, cancellationToken);\r\n    }\r\n\r\n    public Task Send<TRequest>(TRequest request, CancellationToken cancellationToken = default)\r\n        where TRequest : IRequest\r\n    {\r\n        if (request == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(request));\r\n        }\r\n\r\n        var handler = (RequestHandlerWrapper)_requestHandlers.GetOrAdd(request.GetType(), static requestType =>\r\n        {\r\n            var wrapperType = typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestType);\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper type for {requestType}\");\r\n            return (RequestHandlerBase)wrapper;\r\n        });\r\n\r\n        return handler.Handle(request, _serviceProvider, cancellationToken);\r\n    }\r\n\r\n    public Task<object?> Send(object request, CancellationToken cancellationToken = default)\r\n    {\r\n        if (request == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(request));\r\n        }\r\n\r\n        var handler = _requestHandlers.GetOrAdd(request.GetType(), static requestType =>\r\n        {\r\n            Type wrapperType;\r\n\r\n            var requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>));\r\n            if (requestInterfaceType is null)\r\n            {\r\n                requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i == typeof(IRequest));\r\n                if (requestInterfaceType is null)\r\n                {\r\n                    throw new ArgumentException($\"{requestType.Name} does not implement {nameof(IRequest)}\", nameof(request));\r\n                }\r\n\r\n                wrapperType = typeof(RequestHandlerWrapperImpl<>).MakeGenericType(requestType);\r\n            }\r\n            else\r\n            {\r\n                var responseType = requestInterfaceType.GetGenericArguments()[0];\r\n                wrapperType = typeof(RequestHandlerWrapperImpl<,>).MakeGenericType(requestType, responseType);\r\n            }\r\n\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper for type {requestType}\");\r\n            return (RequestHandlerBase)wrapper;\r\n        });\r\n\r\n        // call via dynamic dispatch to avoid calling through reflection for performance reasons\r\n        return handler.Handle(request, _serviceProvider, cancellationToken);\r\n    }\r\n\r\n    public Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default)\r\n        where TNotification : INotification\r\n    {\r\n        if (notification == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(notification));\r\n        }\r\n\r\n        return PublishNotification(notification, cancellationToken);\r\n    }\r\n\r\n    public Task Publish(object notification, CancellationToken cancellationToken = default) =>\r\n        notification switch\r\n        {\r\n            null => throw new ArgumentNullException(nameof(notification)),\r\n            INotification instance => PublishNotification(instance, cancellationToken),\r\n            _ => throw new ArgumentException($\"{nameof(notification)} does not implement ${nameof(INotification)}\")\r\n        };\r\n\r\n    /// <summary>\r\n    /// Override in a derived class to control how the tasks are awaited. By default the implementation calls the <see cref=\"INotificationPublisher\"/>.\r\n    /// </summary>\r\n    /// <param name=\"handlerExecutors\">Enumerable of tasks representing invoking each notification handler</param>\r\n    /// <param name=\"notification\">The notification being published</param>\r\n    /// <param name=\"cancellationToken\">The cancellation token</param>\r\n    /// <returns>A task representing invoking all handlers</returns>\r\n    protected virtual Task PublishCore(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken) \r\n        => _publisher.Publish(handlerExecutors, notification, cancellationToken);\r\n\r\n    private Task PublishNotification(INotification notification, CancellationToken cancellationToken = default)\r\n    {\r\n        var handler = _notificationHandlers.GetOrAdd(notification.GetType(), static notificationType =>\r\n        {\r\n            var wrapperType = typeof(NotificationHandlerWrapperImpl<>).MakeGenericType(notificationType);\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper for type {notificationType}\");\r\n            return (NotificationHandlerWrapper)wrapper;\r\n        });\r\n\r\n        return handler.Handle(notification, _serviceProvider, PublishCore, cancellationToken);\r\n    }\r\n\r\n\r\n    public IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamRequest<TResponse> request, CancellationToken cancellationToken = default)\r\n    {\r\n        if (request == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(request));\r\n        }\r\n\r\n        var streamHandler = (StreamRequestHandlerWrapper<TResponse>)_streamRequestHandlers.GetOrAdd(request.GetType(), static requestType =>\r\n        {\r\n            var wrapperType = typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestType, typeof(TResponse));\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper for type {requestType}\");\r\n            return (StreamRequestHandlerBase)wrapper;\r\n        });\r\n\r\n        var items = streamHandler.Handle(request, _serviceProvider, cancellationToken);\r\n\r\n        return items;\r\n    }\r\n\r\n\r\n    public IAsyncEnumerable<object?> CreateStream(object request, CancellationToken cancellationToken = default)\r\n    {\r\n        if (request == null)\r\n        {\r\n            throw new ArgumentNullException(nameof(request));\r\n        }\r\n\r\n        var handler = _streamRequestHandlers.GetOrAdd(request.GetType(), static requestType =>\r\n        {\r\n            var requestInterfaceType = requestType.GetInterfaces().FirstOrDefault(static i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IStreamRequest<>));\r\n            if (requestInterfaceType is null)\r\n            {\r\n                throw new ArgumentException($\"{requestType.Name} does not implement IStreamRequest<TResponse>\", nameof(request));\r\n            }\r\n\r\n            var responseType = requestInterfaceType.GetGenericArguments()[0];\r\n            var wrapperType = typeof(StreamRequestHandlerWrapperImpl<,>).MakeGenericType(requestType, responseType);\r\n            var wrapper = Activator.CreateInstance(wrapperType) ?? throw new InvalidOperationException($\"Could not create wrapper for type {requestType}\");\r\n            return (StreamRequestHandlerBase)wrapper;\r\n        });\r\n\r\n        var items = handler.Handle(request, _serviceProvider, cancellationToken);\r\n\r\n        return items;\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/MediatR/MicrosoftExtensionsDI/MediatRServiceCollectionExtensions.cs",
    "content": "using System;\nusing System.Linq;\nusing MediatR;\nusing MediatR.Licensing;\nusing MediatR.Pipeline;\nusing MediatR.Registration;\nusing Microsoft.Extensions.Logging;\n\nnamespace Microsoft.Extensions.DependencyInjection;\n\n/// <summary>\n/// Extensions to scan for MediatR handlers and registers them.\n/// - Scans for any handler interface implementations and registers them as <see cref=\"ServiceLifetime.Transient\"/>\n/// - Scans for any <see cref=\"IRequestPreProcessor{TRequest}\"/> and <see cref=\"IRequestPostProcessor{TRequest,TResponse}\"/> implementations and registers them as transient instances\n/// Registers <see cref=\"IMediator\"/> as a transient instance\n/// After calling AddMediatR you can use the container to resolve an <see cref=\"IMediator\"/> instance.\n/// This does not scan for any <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> instances including <see cref=\"RequestPreProcessorBehavior{TRequest,TResponse}\"/> and <see cref=\"RequestPreProcessorBehavior{TRequest,TResponse}\"/>.\n/// To register behaviors, use the <see cref=\"ServiceCollectionServiceExtensions.AddTransient(IServiceCollection,Type,Type)\"/> with the open generic or closed generic types.\n/// </summary>\npublic static class MediatRServiceCollectionExtensions\n{\n    /// <summary>\n    /// Registers handlers and mediator types from the specified assemblies\n    /// </summary>\n    /// <param name=\"services\">Service collection</param>\n    /// <param name=\"configuration\">The action used to configure the options</param>\n    /// <returns>Service collection</returns>\n    public static IServiceCollection AddMediatR(this IServiceCollection services, \n        Action<MediatRServiceConfiguration> configuration)\n    {\n        var serviceConfig = new MediatRServiceConfiguration();\n\n        configuration.Invoke(serviceConfig);\n\n        return services.AddMediatR(serviceConfig);\n    }\n    \n    /// <summary>\n    /// Registers handlers and mediator types from the specified assemblies\n    /// </summary>\n    /// <param name=\"services\">Service collection</param>\n    /// <param name=\"configuration\">Configuration options</param>\n    /// <returns>Service collection</returns>\n    public static IServiceCollection AddMediatR(this IServiceCollection services, \n        MediatRServiceConfiguration configuration)\n    {\n        if (!configuration.AssembliesToRegister.Any())\n        {\n            throw new ArgumentException(\"No assemblies found to scan. Supply at least one assembly to scan for handlers.\");\n        }\n\n        ServiceRegistrar.SetGenericRequestHandlerRegistrationLimitations(configuration);\n\n        ServiceRegistrar.AddMediatRClassesWithTimeout(services, configuration);\n\n        ServiceRegistrar.AddRequiredServices(services, configuration);\n\n        return services;\n    }\n    \n    internal static void CheckLicense(this IServiceProvider serviceProvider)\n    {\n        if (LicenseChecked == false)\n        {\n            var licenseAccessor = serviceProvider.GetRequiredService<LicenseAccessor>();\n            var licenseValidator = serviceProvider.GetRequiredService<LicenseValidator>();\n            \n            var license = licenseAccessor.Current;\n            licenseValidator.Validate(license);\n        }\n\n        LicenseChecked = true;\n    }\n\n    internal static bool LicenseChecked { get; set; }\n}"
  },
  {
    "path": "src/MediatR/MicrosoftExtensionsDI/MediatrServiceConfiguration.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Reflection;\r\nusing MediatR;\r\nusing MediatR.Entities;\r\nusing MediatR.NotificationPublishers;\r\nusing MediatR.Pipeline;\r\nusing MediatR.Registration;\r\n\r\nnamespace Microsoft.Extensions.DependencyInjection;\r\n\r\npublic class MediatRServiceConfiguration\r\n{\r\n    /// <summary>\r\n    /// Optional filter for types to register. Default value is a function returning true.\r\n    /// </summary>\r\n    public Func<Type, bool> TypeEvaluator { get; set; } = t => true;\r\n    \r\n    /// <summary>\r\n    /// Mediator implementation type to register. Default is <see cref=\"Mediator\"/>\r\n    /// </summary>\r\n    public Type MediatorImplementationType { get; set; } = typeof(Mediator);\r\n\r\n    /// <summary>\r\n    /// Strategy for publishing notifications. Defaults to <see cref=\"ForeachAwaitPublisher\"/>\r\n    /// </summary>\r\n    public INotificationPublisher NotificationPublisher { get; set; } = new ForeachAwaitPublisher();\r\n\r\n    /// <summary>\r\n    /// Type of notification publisher strategy to register. If set, overrides <see cref=\"NotificationPublisher\"/>\r\n    /// </summary>\r\n    public Type? NotificationPublisherType { get; set; }\r\n\r\n    /// <summary>\r\n    /// Service lifetime to register services under. Default value is <see cref=\"ServiceLifetime.Transient\"/>\r\n    /// </summary>\r\n    public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Transient;\r\n\r\n    /// <summary>\r\n    /// Request exception action processor strategy. Default value is <see cref=\"DependencyInjection.RequestExceptionActionProcessorStrategy.ApplyForUnhandledExceptions\"/>\r\n    /// </summary>\r\n    public RequestExceptionActionProcessorStrategy RequestExceptionActionProcessorStrategy { get; set; }\r\n        = RequestExceptionActionProcessorStrategy.ApplyForUnhandledExceptions;\r\n\r\n    internal List<Assembly> AssembliesToRegister { get; } = new();\r\n\r\n    /// <summary>\r\n    /// List of behaviors to register in specific order\r\n    /// </summary>\r\n    public List<ServiceDescriptor> BehaviorsToRegister { get; } = new();\r\n\r\n    /// <summary>\r\n    /// List of stream behaviors to register in specific order\r\n    /// </summary>\r\n    public List<ServiceDescriptor> StreamBehaviorsToRegister { get; } = new();\r\n\r\n    /// <summary>\r\n    /// List of request pre processors to register in specific order\r\n    /// </summary>\r\n    public List<ServiceDescriptor> RequestPreProcessorsToRegister { get; } = new();\r\n\r\n    /// <summary>\r\n    /// List of request post processors to register in specific order\r\n    /// </summary>\r\n    public List<ServiceDescriptor> RequestPostProcessorsToRegister { get; } = new();\r\n\r\n    /// <summary>\r\n    /// Automatically register processors during assembly scanning\r\n    /// </summary>\r\n    public bool AutoRegisterRequestProcessors { get; set; }\r\n\r\n    /// <summary>\r\n    /// Configure the maximum number of type parameters that a generic request handler can have. To Disable this constraint, set the value to 0.\r\n    /// </summary>\r\n    public int MaxGenericTypeParameters { get; set; } = 10;\r\n\r\n    /// <summary>\r\n    /// Configure the maximum number of types that can close a generic request type parameter constraint.  To Disable this constraint, set the value to 0.\r\n    /// </summary>\r\n    public int MaxTypesClosing { get; set; } = 100;\r\n\r\n    /// <summary>\r\n    /// Configure the Maximum Amount of Generic RequestHandler Types MediatR will try to register.  To Disable this constraint, set the value to 0.\r\n    /// </summary>\r\n    public int MaxGenericTypeRegistrations { get; set; } = 125000;\r\n\r\n    /// <summary>\r\n    /// Configure the Timeout in Milliseconds that the GenericHandler Registration Process will exit with error.  To Disable this constraint, set the value to 0.\r\n    /// </summary>\r\n    public int RegistrationTimeout { get; set; } = 15000;\r\n\r\n    /// <summary>\r\n    /// Flag that controlls whether MediatR will attempt to register handlers that containg generic type parameters.\r\n    /// </summary>\r\n    public bool RegisterGenericHandlers { get; set; } = false;\r\n\r\n    /// <summary>\r\n    /// Gets or sets the license key. You can find your license key in your <a href=\"https://luckypennysoftware.com/account\">account</a>.\r\n    /// </summary>\r\n    public string? LicenseKey { get; set; }\r\n\r\n    /// <summary>\r\n    /// Register various handlers from assembly containing given type\r\n    /// </summary>\r\n    /// <typeparam name=\"T\">Type from assembly to scan</typeparam>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration RegisterServicesFromAssemblyContaining<T>()\r\n        => RegisterServicesFromAssemblyContaining(typeof(T));\r\n\r\n    /// <summary>\r\n    /// Register various handlers from assembly containing given type\r\n    /// </summary>\r\n    /// <param name=\"type\">Type from assembly to scan</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration RegisterServicesFromAssemblyContaining(Type type)\r\n        => RegisterServicesFromAssembly(type.Assembly);\r\n\r\n    /// <summary>\r\n    /// Register various handlers from assembly\r\n    /// </summary>\r\n    /// <param name=\"assembly\">Assembly to scan</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration RegisterServicesFromAssembly(Assembly assembly)\r\n    {\r\n        AssembliesToRegister.Add(assembly);\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register various handlers from assemblies\r\n    /// </summary>\r\n    /// <param name=\"assemblies\">Assemblies to scan</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration RegisterServicesFromAssemblies(\r\n        params Assembly[] assemblies)\r\n    {\r\n        AssembliesToRegister.AddRange(assemblies);\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register a closed behavior type\r\n    /// </summary>\r\n    /// <typeparam name=\"TServiceType\">Closed behavior interface type</typeparam>\r\n    /// <typeparam name=\"TImplementationType\">Closed behavior implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddBehavior<TServiceType, TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddBehavior(typeof(TServiceType), typeof(TImplementationType), serviceLifetime);\r\n\r\n    /// <summary>\r\n    /// Register a closed behavior type against all <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <typeparam name=\"TImplementationType\">Closed behavior implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddBehavior<TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        return AddBehavior(typeof(TImplementationType), serviceLifetime);\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register a closed behavior type against all <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <param name=\"implementationType\">Closed behavior implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddBehavior(Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        var implementedGenericInterfaces = implementationType.FindInterfacesThatClose(typeof(IPipelineBehavior<,>)).ToList();\r\n\r\n        if (implementedGenericInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{implementationType.Name} must implement {typeof(IPipelineBehavior<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var implementedBehaviorType in implementedGenericInterfaces)\r\n        {\r\n            BehaviorsToRegister.Add(new ServiceDescriptor(implementedBehaviorType, implementationType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register a closed behavior type\r\n    /// </summary>\r\n    /// <param name=\"serviceType\">Closed behavior interface type</param>\r\n    /// <param name=\"implementationType\">Closed behavior implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddBehavior(Type serviceType, Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        BehaviorsToRegister.Add(new ServiceDescriptor(serviceType, implementationType, serviceLifetime));\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Registers an open behavior type against the <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviorType\">An open generic behavior type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenBehavior(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        if (!openBehaviorType.IsGenericType)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must be generic\");\r\n        }\r\n\r\n        var implementedGenericInterfaces = openBehaviorType.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition());\r\n        var implementedOpenBehaviorInterfaces = new HashSet<Type>(implementedGenericInterfaces.Where(i => i == typeof(IPipelineBehavior<,>)));\r\n\r\n        if (implementedOpenBehaviorInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must implement {typeof(IPipelineBehavior<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var openBehaviorInterface in implementedOpenBehaviorInterfaces)\r\n        {\r\n            BehaviorsToRegister.Add(new ServiceDescriptor(openBehaviorInterface, openBehaviorType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Registers multiple open behavior types against the <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviorTypes\">An open generic behavior type list includes multiple open generic behavior types.</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenBehaviors(IEnumerable<Type> openBehaviorTypes, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        foreach (var openBehaviorType in openBehaviorTypes)\r\n        {\r\n            AddOpenBehavior(openBehaviorType, serviceLifetime);\r\n        }\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Registers open behaviors against the <see cref=\"IPipelineBehavior{TRequest,TResponse}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviors\">An open generic behavior list includes multiple <see cref=\"OpenBehavior\"/> open generic behaviors.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenBehaviors(IEnumerable<OpenBehavior> openBehaviors)\r\n    {\r\n        foreach (var openBehavior in openBehaviors)\r\n        {\r\n            AddOpenBehavior(openBehavior.OpenBehaviorType!, openBehavior.ServiceLifetime);\r\n        }\r\n\r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Register a closed stream behavior type\r\n    /// </summary>\r\n    /// <typeparam name=\"TServiceType\">Closed stream behavior interface type</typeparam>\r\n    /// <typeparam name=\"TImplementationType\">Closed stream behavior implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddStreamBehavior<TServiceType, TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddStreamBehavior(typeof(TServiceType), typeof(TImplementationType), serviceLifetime);\r\n    \r\n    /// <summary>\r\n    /// Register a closed stream behavior type\r\n    /// </summary>\r\n    /// <param name=\"serviceType\">Closed stream behavior interface type</param>\r\n    /// <param name=\"implementationType\">Closed stream behavior implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddStreamBehavior(Type serviceType, Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        StreamBehaviorsToRegister.Add(new ServiceDescriptor(serviceType, implementationType, serviceLifetime));\r\n\r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Register a closed stream behavior type against all <see cref=\"IStreamPipelineBehavior{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <typeparam name=\"TImplementationType\">Closed stream behavior implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddStreamBehavior<TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddStreamBehavior(typeof(TImplementationType), serviceLifetime);\r\n    \r\n    /// <summary>\r\n    /// Register a closed stream behavior type against all <see cref=\"IStreamPipelineBehavior{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <param name=\"implementationType\">Closed stream behavior implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddStreamBehavior(Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        var implementedGenericInterfaces = implementationType.FindInterfacesThatClose(typeof(IStreamPipelineBehavior<,>)).ToList();\r\n\r\n        if (implementedGenericInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{implementationType.Name} must implement {typeof(IStreamPipelineBehavior<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var implementedBehaviorType in implementedGenericInterfaces)\r\n        {\r\n            StreamBehaviorsToRegister.Add(new ServiceDescriptor(implementedBehaviorType, implementationType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Registers an open stream behavior type against the <see cref=\"IStreamPipelineBehavior{TRequest,TResponse}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviorType\">An open generic stream behavior type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenStreamBehavior(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        if (!openBehaviorType.IsGenericType)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must be generic\");\r\n        }\r\n\r\n        var implementedGenericInterfaces = openBehaviorType.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition());\r\n        var implementedOpenBehaviorInterfaces = new HashSet<Type>(implementedGenericInterfaces.Where(i => i == typeof(IStreamPipelineBehavior<,>)));\r\n\r\n        if (implementedOpenBehaviorInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must implement {typeof(IStreamPipelineBehavior<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var openBehaviorInterface in implementedOpenBehaviorInterfaces)\r\n        {\r\n            StreamBehaviorsToRegister.Add(new ServiceDescriptor(openBehaviorInterface, openBehaviorType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register a closed request pre processor type\r\n    /// </summary>\r\n    /// <typeparam name=\"TServiceType\">Closed request pre processor interface type</typeparam>\r\n    /// <typeparam name=\"TImplementationType\">Closed request pre processor implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPreProcessor<TServiceType, TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddRequestPreProcessor(typeof(TServiceType), typeof(TImplementationType), serviceLifetime);\r\n    \r\n    /// <summary>\r\n    /// Register a closed request pre processor type\r\n    /// </summary>\r\n    /// <param name=\"serviceType\">Closed request pre processor interface type</param>\r\n    /// <param name=\"implementationType\">Closed request pre processor implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPreProcessor(Type serviceType, Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        RequestPreProcessorsToRegister.Add(new ServiceDescriptor(serviceType, implementationType, serviceLifetime));\r\n\r\n        return this;\r\n    }\r\n\r\n    /// <summary>\r\n    /// Register a closed request pre processor type against all <see cref=\"IRequestPreProcessor{TRequest}\"/> implementations\r\n    /// </summary>\r\n    /// <typeparam name=\"TImplementationType\">Closed request pre processor implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPreProcessor<TImplementationType>(\r\n        ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddRequestPreProcessor(typeof(TImplementationType), serviceLifetime);\r\n\r\n    /// <summary>\r\n    /// Register a closed request pre processor type against all <see cref=\"IRequestPreProcessor{TRequest}\"/> implementations\r\n    /// </summary>\r\n    /// <param name=\"implementationType\">Closed request pre processor implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPreProcessor(Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        var implementedGenericInterfaces = implementationType.FindInterfacesThatClose(typeof(IRequestPreProcessor<>)).ToList();\r\n\r\n        if (implementedGenericInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{implementationType.Name} must implement {typeof(IRequestPreProcessor<>).FullName}\");\r\n        }\r\n\r\n        foreach (var implementedPreProcessorType in implementedGenericInterfaces)\r\n        {\r\n            RequestPreProcessorsToRegister.Add(new ServiceDescriptor(implementedPreProcessorType, implementationType, serviceLifetime));\r\n        }\r\n        \r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Registers an open request pre processor type against the <see cref=\"IRequestPreProcessor{TRequest}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviorType\">An open generic request pre processor type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenRequestPreProcessor(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        if (!openBehaviorType.IsGenericType)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must be generic\");\r\n        }\r\n\r\n        var implementedGenericInterfaces = openBehaviorType.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition());\r\n        var implementedOpenBehaviorInterfaces = new HashSet<Type>(implementedGenericInterfaces.Where(i => i == typeof(IRequestPreProcessor<>)));\r\n\r\n        if (implementedOpenBehaviorInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must implement {typeof(IRequestPreProcessor<>).FullName}\");\r\n        }\r\n\r\n        foreach (var openBehaviorInterface in implementedOpenBehaviorInterfaces)\r\n        {\r\n            RequestPreProcessorsToRegister.Add(new ServiceDescriptor(openBehaviorInterface, openBehaviorType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Register a closed request post processor type\r\n    /// </summary>\r\n    /// <typeparam name=\"TServiceType\">Closed request post processor interface type</typeparam>\r\n    /// <typeparam name=\"TImplementationType\">Closed request post processor implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPostProcessor<TServiceType, TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddRequestPostProcessor(typeof(TServiceType), typeof(TImplementationType), serviceLifetime);\r\n    \r\n    /// <summary>\r\n    /// Register a closed request post processor type\r\n    /// </summary>\r\n    /// <param name=\"serviceType\">Closed request post processor interface type</param>\r\n    /// <param name=\"implementationType\">Closed request post processor implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPostProcessor(Type serviceType, Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        RequestPostProcessorsToRegister.Add(new ServiceDescriptor(serviceType, implementationType, serviceLifetime));\r\n\r\n        return this;\r\n    }\r\n \r\n    /// <summary>\r\n    /// Register a closed request post processor type against all <see cref=\"IRequestPostProcessor{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <typeparam name=\"TImplementationType\">Closed request post processor implementation type</typeparam>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPostProcessor<TImplementationType>(ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n        => AddRequestPostProcessor(typeof(TImplementationType), serviceLifetime);\r\n    \r\n    /// <summary>\r\n    /// Register a closed request post processor type against all <see cref=\"IRequestPostProcessor{TRequest,TResponse}\"/> implementations\r\n    /// </summary>\r\n    /// <param name=\"implementationType\">Closed request post processor implementation type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddRequestPostProcessor(Type implementationType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        var implementedGenericInterfaces = implementationType.FindInterfacesThatClose(typeof(IRequestPostProcessor<,>)).ToList();\r\n\r\n        if (implementedGenericInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{implementationType.Name} must implement {typeof(IRequestPostProcessor<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var implementedPostProcessorType in implementedGenericInterfaces)\r\n        {\r\n            RequestPostProcessorsToRegister.Add(new ServiceDescriptor(implementedPostProcessorType, implementationType, serviceLifetime));\r\n        }\r\n        return this;\r\n    }\r\n    \r\n    /// <summary>\r\n    /// Registers an open request post processor type against the <see cref=\"IRequestPostProcessor{TRequest,TResponse}\"/> open generic interface type\r\n    /// </summary>\r\n    /// <param name=\"openBehaviorType\">An open generic request post processor type</param>\r\n    /// <param name=\"serviceLifetime\">Optional service lifetime, defaults to <see cref=\"ServiceLifetime.Transient\"/>.</param>\r\n    /// <returns>This</returns>\r\n    public MediatRServiceConfiguration AddOpenRequestPostProcessor(Type openBehaviorType, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)\r\n    {\r\n        if (!openBehaviorType.IsGenericType)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must be generic\");\r\n        }\r\n\r\n        var implementedGenericInterfaces = openBehaviorType.GetInterfaces().Where(i => i.IsGenericType).Select(i => i.GetGenericTypeDefinition());\r\n        var implementedOpenBehaviorInterfaces = new HashSet<Type>(implementedGenericInterfaces.Where(i => i == typeof(IRequestPostProcessor<,>)));\r\n\r\n        if (implementedOpenBehaviorInterfaces.Count == 0)\r\n        {\r\n            throw new InvalidOperationException($\"{openBehaviorType.Name} must implement {typeof(IRequestPostProcessor<,>).FullName}\");\r\n        }\r\n\r\n        foreach (var openBehaviorInterface in implementedOpenBehaviorInterfaces)\r\n        {\r\n            RequestPostProcessorsToRegister.Add(new ServiceDescriptor(openBehaviorInterface, openBehaviorType, serviceLifetime));\r\n        }\r\n\r\n        return this;\r\n    }\r\n\r\n\r\n}"
  },
  {
    "path": "src/MediatR/MicrosoftExtensionsDI/RequestExceptionActionProcessorStrategy.cs",
    "content": "﻿namespace Microsoft.Extensions.DependencyInjection;\n\npublic enum RequestExceptionActionProcessorStrategy\n{\n    ApplyForUnhandledExceptions,\n    ApplyForAllExceptions\n}"
  },
  {
    "path": "src/MediatR/NotificationHandlerExecutor.cs",
    "content": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR;\n\npublic record NotificationHandlerExecutor(object HandlerInstance, Func<INotification, CancellationToken, Task> HandlerCallback);"
  },
  {
    "path": "src/MediatR/NotificationPublishers/ForeachAwaitPublisher.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.NotificationPublishers;\n\n/// <summary>\n/// Awaits each notification handler in a single foreach loop:\n/// <code>\n/// foreach (var handler in handlers) {\n///     await handler(notification, cancellationToken);\n/// }\n/// </code>\n/// </summary>\npublic class ForeachAwaitPublisher : INotificationPublisher\n{\n    public async Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)\n    {\n        foreach (var handler in handlerExecutors)\n        {\n            await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);\n        }\n    }\n}"
  },
  {
    "path": "src/MediatR/NotificationPublishers/TaskWhenAllPublisher.cs",
    "content": "﻿using System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.NotificationPublishers;\n\n/// <summary>\n/// Uses Task.WhenAll with the list of Handler tasks:\n/// <code>\n/// var tasks = handlers\n///                .Select(handler => handler.Handle(notification, cancellationToken))\n///                .ToList();\n/// \n/// return Task.WhenAll(tasks);\n/// </code>\n/// </summary>\npublic class TaskWhenAllPublisher : INotificationPublisher\n{\n    public Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)\n    {\n        var tasks = handlerExecutors\n            .Select(handler => handler.HandlerCallback(notification, cancellationToken))\n            .ToArray();\n\n        return Task.WhenAll(tasks);\n    }\n}"
  },
  {
    "path": "src/MediatR/Pipeline/IRequestExceptionAction.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n    \n/// <summary>\n/// Defines an exception action for a request\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TException\">Exception type</typeparam>\npublic interface IRequestExceptionAction<in TRequest, in TException>\n    where TRequest : notnull\n    where TException : Exception\n{\n    /// <summary>\n    /// Called when the request handler throws an exception\n    /// </summary>\n    /// <param name=\"request\">Request instance</param>\n    /// <param name=\"exception\">The thrown exception</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>An awaitable task</returns>\n    Task Execute(TRequest request, TException exception, CancellationToken cancellationToken);\n}\n"
  },
  {
    "path": "src/MediatR/Pipeline/IRequestExceptionHandler.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Defines an exception handler for a request and response\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\n/// <typeparam name=\"TException\">Exception type</typeparam>\npublic interface IRequestExceptionHandler<in TRequest, TResponse, in TException>\n    where TRequest : notnull\n    where TException : Exception\n{\n    /// <summary>\n    /// Called when the request handler throws an exception\n    /// </summary>\n    /// <param name=\"request\">Request instance</param>\n    /// <param name=\"exception\">The thrown exception</param>\n    /// <param name=\"state\">The current state of handling the exception</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>An awaitable task</returns>\n    Task Handle(TRequest request, TException exception, RequestExceptionHandlerState<TResponse> state, CancellationToken cancellationToken);\n}\n"
  },
  {
    "path": "src/MediatR/Pipeline/IRequestPostProcessor.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Defines a request post-processor for a request\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic interface IRequestPostProcessor<in TRequest, in TResponse> where TRequest : notnull\n{\n    /// <summary>\n    /// Process method executes after the Handle method on your handler\n    /// </summary>\n    /// <param name=\"request\">Request instance</param>\n    /// <param name=\"response\">Response instance</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>An awaitable task</returns>\n    Task Process(TRequest request, TResponse response, CancellationToken cancellationToken);\n}"
  },
  {
    "path": "src/MediatR/Pipeline/IRequestPreProcessor.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Defined a request pre-processor for a handler\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\npublic interface IRequestPreProcessor<in TRequest> where TRequest : notnull\n{\n    /// <summary>\n    /// Process method executes before calling the Handle method on your handler\n    /// </summary>\n    /// <param name=\"request\">Incoming request</param>\n    /// <param name=\"cancellationToken\">Cancellation token</param>\n    /// <returns>An awaitable task</returns>\n    Task Process(TRequest request, CancellationToken cancellationToken);\n}"
  },
  {
    "path": "src/MediatR/Pipeline/RequestExceptionActionProcessorBehavior.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing Internal;\nusing Microsoft.Extensions.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.ExceptionServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Behavior for executing all <see cref=\"IRequestExceptionAction{TRequest,TException}\"/> instances\n///     after an exception is thrown by the following pipeline steps\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic class RequestExceptionActionProcessorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n    where TRequest : notnull\n{\n    private readonly IServiceProvider _serviceProvider;\n\n    public RequestExceptionActionProcessorBehavior(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;\n\n    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n    {\n        try\n        {\n            return await next(cancellationToken).ConfigureAwait(false);\n        }\n        catch (Exception exception)\n        {\n            var exceptionTypes = GetExceptionTypes(exception.GetType());\n\n            var actionsForException = exceptionTypes\n                .SelectMany(exceptionType => GetActionsForException(exceptionType, request))\n                .GroupBy(static actionForException => actionForException.Action.GetType())\n                .Select(static actionForException => actionForException.First())\n                .Select(static actionForException => (MethodInfo: GetMethodInfoForAction(actionForException.ExceptionType), actionForException.Action))\n                .ToList();\n\n            foreach (var actionForException in actionsForException)\n            {\n                try\n                {\n                    await ((Task)(actionForException.MethodInfo.Invoke(actionForException.Action, new object[] { request, exception, cancellationToken })\n                                  ?? throw new InvalidOperationException($\"Could not create task for action method {actionForException.MethodInfo}.\"))).ConfigureAwait(false);\n                }\n                catch (TargetInvocationException invocationException) when (invocationException.InnerException != null)\n                {\n                    // Unwrap invocation exception to throw the actual error\n                    ExceptionDispatchInfo.Capture(invocationException.InnerException).Throw();\n                }\n            }\n\n            throw;\n        }\n    }\n\n    private static IEnumerable<Type> GetExceptionTypes(Type? exceptionType)\n    {\n        while (exceptionType != null && exceptionType != typeof(object))\n        {\n            yield return exceptionType;\n            exceptionType = exceptionType.BaseType;\n        }\n    }\n\n    private IEnumerable<(Type ExceptionType, object Action)> GetActionsForException(Type exceptionType, TRequest request)\n    {\n        var exceptionActionInterfaceType = typeof(IRequestExceptionAction<,>).MakeGenericType(typeof(TRequest), exceptionType);\n        var enumerableExceptionActionInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionActionInterfaceType);\n\n        var actionsForException = (IEnumerable<object>)_serviceProvider.GetRequiredService(enumerableExceptionActionInterfaceType);\n\n        return HandlersOrderer.Prioritize(actionsForException.ToList(), request)\n            .Select(action => (exceptionType, action));\n    }\n\n    private static MethodInfo GetMethodInfoForAction(Type exceptionType)\n    {\n        var exceptionActionInterfaceType = typeof(IRequestExceptionAction<,>).MakeGenericType(typeof(TRequest), exceptionType);\n\n        var actionMethodInfo =\n            exceptionActionInterfaceType.GetMethod(nameof(IRequestExceptionAction<TRequest, Exception>.Execute))\n            ?? throw new InvalidOperationException(\n                $\"Could not find method {nameof(IRequestExceptionAction<TRequest, Exception>.Execute)} on type {exceptionActionInterfaceType}\");\n\n        return actionMethodInfo;\n    }\n}\n"
  },
  {
    "path": "src/MediatR/Pipeline/RequestExceptionHandlerState.cs",
    "content": "namespace MediatR.Pipeline;\n\n/// <summary>\n/// Represents the result of handling an exception thrown by a request handler\n/// </summary>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic class RequestExceptionHandlerState<TResponse>\n{\n    /// <summary>\n    /// Indicates whether the current exception has been handled and the response should be returned.\n    /// </summary>\n    public bool Handled { get; private set; }\n\n    /// <summary>\n    /// The response that is returned if <see cref=\"Handled\"/> is <code>true</code>.\n    /// </summary>\n    public TResponse? Response { get; private set; }\n\n    /// <summary>\n    /// Call to indicate whether the current exception should be considered handled and the specified response should be returned.\n    /// </summary>\n    /// <param name=\"response\">Set the response that will be returned.</param>\n    public void SetHandled(TResponse response)\n    {\n        Handled = true;\n        Response = response;\n    }\n}"
  },
  {
    "path": "src/MediatR/Pipeline/RequestExceptionProcessorBehavior.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing Internal;\nusing Microsoft.Extensions.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Runtime.ExceptionServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Behavior for executing all <see cref=\"IRequestExceptionHandler{TRequest,TResponse,TException}\"/> instances\n///     after an exception is thrown by the following pipeline steps\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic class RequestExceptionProcessorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n    where TRequest : notnull\n{\n    private readonly IServiceProvider _serviceProvider;\n\n    public RequestExceptionProcessorBehavior(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;\n\n    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n    {\n        try\n        {\n            return await next(cancellationToken).ConfigureAwait(false);\n        }\n        catch (Exception exception)\n        {\n            var state = new RequestExceptionHandlerState<TResponse>();\n\n            var exceptionTypes = GetExceptionTypes(exception.GetType());\n\n            var handlersForException = exceptionTypes\n                .SelectMany(exceptionType => GetHandlersForException(exceptionType, request))\n                .GroupBy(static handlerForException => handlerForException.Handler.GetType())\n                .Select(static handlerForException => handlerForException.First())\n                .Select(static handlerForException => (MethodInfo: GetMethodInfoForHandler(handlerForException.ExceptionType), handlerForException.Handler))\n                .ToList();\n\n            foreach (var handlerForException in handlersForException)\n            {\n                try\n                {\n                    await ((Task) (handlerForException.MethodInfo.Invoke(handlerForException.Handler, new object[] { request, exception, state, cancellationToken })\n                                   ?? throw new InvalidOperationException(\"Did not return a Task from the exception handler.\"))).ConfigureAwait(false);\n                }\n                catch (TargetInvocationException invocationException) when (invocationException.InnerException != null)\n                {\n                    // Unwrap invocation exception to throw the actual error\n                    ExceptionDispatchInfo.Capture(invocationException.InnerException).Throw();\n                }\n\n                if (state.Handled)\n                {\n                    break;\n                }\n            }\n\n            if (!state.Handled)\n            {\n                throw;\n            }\n\n            if (state.Response is null)\n            {\n                throw;\n            }\n\n            return state.Response; //cannot be null if Handled\n        }\n    }\n    private static IEnumerable<Type> GetExceptionTypes(Type? exceptionType)\n    {\n        while (exceptionType != null && exceptionType != typeof(object))\n        {\n            yield return exceptionType;\n            exceptionType = exceptionType.BaseType;\n        }\n    }\n\n    private IEnumerable<(Type ExceptionType, object Handler)> GetHandlersForException(Type exceptionType, TRequest request)\n    {\n        var exceptionHandlerInterfaceType = typeof(IRequestExceptionHandler<,,>).MakeGenericType(typeof(TRequest), typeof(TResponse), exceptionType);\n        var enumerableExceptionHandlerInterfaceType = typeof(IEnumerable<>).MakeGenericType(exceptionHandlerInterfaceType);\n\n        var exceptionHandlers = (IEnumerable<object>) _serviceProvider.GetRequiredService(enumerableExceptionHandlerInterfaceType);\n\n        return HandlersOrderer.Prioritize(exceptionHandlers.ToList(), request)\n            .Select(handler => (exceptionType, action: handler));\n    }\n\n    private static MethodInfo GetMethodInfoForHandler(Type exceptionType)\n    {\n        var exceptionHandlerInterfaceType = typeof(IRequestExceptionHandler<,,>).MakeGenericType(typeof(TRequest), typeof(TResponse), exceptionType);\n        \n        var handleMethodInfo = exceptionHandlerInterfaceType.GetMethod(nameof(IRequestExceptionHandler<TRequest, TResponse, Exception>.Handle))\n                           ?? throw new InvalidOperationException($\"Could not find method {nameof(IRequestExceptionHandler<TRequest, TResponse, Exception>.Handle)} on type {exceptionHandlerInterfaceType}\");\n\n        return handleMethodInfo;\n    }\n}"
  },
  {
    "path": "src/MediatR/Pipeline/RequestPostProcessorBehavior.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Behavior for executing all <see cref=\"IRequestPostProcessor{TRequest,TResponse}\"/> instances after handling the request\n/// </summary>\n/// <typeparam name=\"TRequest\">Request type</typeparam>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic class RequestPostProcessorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n    where TRequest : notnull\n{\n    private readonly IEnumerable<IRequestPostProcessor<TRequest, TResponse>> _postProcessors;\n\n    public RequestPostProcessorBehavior(IEnumerable<IRequestPostProcessor<TRequest, TResponse>> postProcessors) \n        => _postProcessors = postProcessors;\n\n    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n    {\n        var response = await next(cancellationToken).ConfigureAwait(false);\n\n        foreach (var processor in _postProcessors)\n        {\n            await processor.Process(request, response, cancellationToken).ConfigureAwait(false);\n        }\n\n        return response;\n    }\n}"
  },
  {
    "path": "src/MediatR/Pipeline/RequestPreProcessorBehavior.cs",
    "content": "namespace MediatR.Pipeline;\n\nusing System.Collections.Generic;\nusing System.Threading;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Behavior for executing all <see cref=\"IRequestPreProcessor{TRequest}\"/> instances before handling a request\n/// </summary>\n/// <typeparam name=\"TRequest\"></typeparam>\n/// <typeparam name=\"TResponse\"></typeparam>\npublic class RequestPreProcessorBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n    where TRequest : notnull\n{\n    private readonly IEnumerable<IRequestPreProcessor<TRequest>> _preProcessors;\n\n    public RequestPreProcessorBehavior(IEnumerable<IRequestPreProcessor<TRequest>> preProcessors) \n        => _preProcessors = preProcessors;\n\n    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n    {\n        foreach (var processor in _preProcessors)\n        {\n            await processor.Process(request, cancellationToken).ConfigureAwait(false);\n        }\n\n        return await next(cancellationToken).ConfigureAwait(false);\n    }\n}"
  },
  {
    "path": "src/MediatR/Registration/ServiceRegistrar.cs",
    "content": "﻿using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing MediatR.Licensing;\nusing MediatR.Pipeline;\nusing Microsoft.Extensions.DependencyInjection;\nusing Microsoft.Extensions.DependencyInjection.Extensions;\nusing Microsoft.Extensions.Logging;\n\nnamespace MediatR.Registration;\n\npublic static class ServiceRegistrar\n{\n    private static int MaxGenericTypeParameters;\n    private static int MaxTypesClosing;\n    private static int MaxGenericTypeRegistrations;\n    private static int RegistrationTimeout; \n\n    public static void SetGenericRequestHandlerRegistrationLimitations(MediatRServiceConfiguration configuration)\n    {\n        MaxGenericTypeParameters = configuration.MaxGenericTypeParameters;\n        MaxTypesClosing = configuration.MaxTypesClosing;\n        MaxGenericTypeRegistrations = configuration.MaxGenericTypeRegistrations;\n        RegistrationTimeout = configuration.RegistrationTimeout;\n    }\n\n    public static void AddMediatRClassesWithTimeout(IServiceCollection services, MediatRServiceConfiguration configuration)\n    {\n        using(var cts = new CancellationTokenSource(RegistrationTimeout))\n        {\n            try\n            {\n                AddMediatRClasses(services, configuration, cts.Token);\n            }\n            catch (OperationCanceledException)\n            {\n                throw new TimeoutException(\"The generic handler registration process timed out.\");\n            }\n        }\n    }\n\n    public static void AddMediatRClasses(IServiceCollection services, MediatRServiceConfiguration configuration, CancellationToken cancellationToken = default)\n    {   \n\n        var assembliesToScan = configuration.AssembliesToRegister.Distinct().ToArray();\n\n        ConnectImplementationsToTypesClosing(typeof(IRequestHandler<,>), services, assembliesToScan, false, configuration, cancellationToken);\n        ConnectImplementationsToTypesClosing(typeof(IRequestHandler<>), services, assembliesToScan, false, configuration, cancellationToken);\n        ConnectImplementationsToTypesClosing(typeof(INotificationHandler<>), services, assembliesToScan, true, configuration);\n        ConnectImplementationsToTypesClosing(typeof(IStreamRequestHandler<,>), services, assembliesToScan, false, configuration);\n        ConnectImplementationsToTypesClosing(typeof(IRequestExceptionHandler<,,>), services, assembliesToScan, true, configuration);\n        ConnectImplementationsToTypesClosing(typeof(IRequestExceptionAction<,>), services, assembliesToScan, true, configuration);\n\n        if (configuration.AutoRegisterRequestProcessors)\n        {\n            ConnectImplementationsToTypesClosing(typeof(IRequestPreProcessor<>), services, assembliesToScan, true, configuration);\n            ConnectImplementationsToTypesClosing(typeof(IRequestPostProcessor<,>), services, assembliesToScan, true, configuration);\n        }\n\n        var multiOpenInterfaces = new List<Type>\n        {\n            typeof(INotificationHandler<>),\n            typeof(IRequestExceptionHandler<,,>),\n            typeof(IRequestExceptionAction<,>)\n        };\n\n        if (configuration.AutoRegisterRequestProcessors)\n        {\n            multiOpenInterfaces.Add(typeof(IRequestPreProcessor<>));\n            multiOpenInterfaces.Add(typeof(IRequestPostProcessor<,>));\n        }\n\n        foreach (var multiOpenInterface in multiOpenInterfaces)\n        {\n            var arity = multiOpenInterface.GetGenericArguments().Length;\n\n            var concretions = assembliesToScan\n                .SelectMany(a => a.GetLoadableDefinedTypes())\n                .Where(type => type.FindInterfacesThatClose(multiOpenInterface).Any())\n                .Where(type => type.IsConcrete() && type.IsOpenGeneric())\n                .Where(type => type.GetGenericArguments().Length == arity)\n                .Where(configuration.TypeEvaluator)\n                .ToList();\n\n            foreach (var type in concretions)\n            {\n                services.AddTransient(multiOpenInterface, type);\n            }\n        }\n    }\n\n    private static void ConnectImplementationsToTypesClosing(Type openRequestInterface,\n        IServiceCollection services,\n        IEnumerable<Assembly> assembliesToScan,\n        bool addIfAlreadyExists,\n        MediatRServiceConfiguration configuration,\n        CancellationToken cancellationToken = default)\n    {\n        var concretions = new List<Type>();\n        var interfaces = new List<Type>();\n        var genericConcretions = new List<Type>();\n        var genericInterfaces = new List<Type>();\n\n        var types = assembliesToScan\n            .SelectMany(a => a.GetLoadableDefinedTypes())\n            .Where(t => !t.ContainsGenericParameters || configuration.RegisterGenericHandlers)\n            .Where(t => t.IsConcrete() && t.FindInterfacesThatClose(openRequestInterface).Any())\n            .Where(configuration.TypeEvaluator)\n            .ToList();\n\n        foreach (var type in types)\n        {\n            var interfaceTypes = type.FindInterfacesThatClose(openRequestInterface).ToArray();\n\n            if (!type.IsOpenGeneric())\n            {\n                concretions.Add(type);\n\n                foreach (var interfaceType in interfaceTypes)\n                {\n                    interfaces.Fill(interfaceType);\n                }\n            }\n            else\n            {\n                genericConcretions.Add(type);\n                foreach (var interfaceType in interfaceTypes)\n                {\n                    genericInterfaces.Fill(interfaceType);\n                }\n            }\n        }\n\n        foreach (var @interface in interfaces)\n        {\n            var exactMatches = concretions.Where(x => x.CanBeCastTo(@interface)).ToList();\n            if (addIfAlreadyExists)\n            {\n                foreach (var type in exactMatches)\n                {\n                    services.AddTransient(@interface, type);\n                }\n            }\n            else\n            {\n                if (exactMatches.Count > 1)\n                {\n                    exactMatches.RemoveAll(m => !IsMatchingWithInterface(m, @interface));\n                }\n\n                foreach (var type in exactMatches)\n                {\n                    services.TryAddTransient(@interface, type);\n                }\n            }\n\n            if (!@interface.IsOpenGeneric())\n            {\n                AddConcretionsThatCouldBeClosed(@interface, concretions, services);\n            }\n        }\n\n        foreach (var @interface in genericInterfaces)\n        {\n            var exactMatches = genericConcretions.Where(x => x.CanBeCastTo(@interface)).ToList();\n            AddAllConcretionsThatClose(@interface, exactMatches, services, assembliesToScan, cancellationToken);\n        }\n    }\n\n    private static bool IsMatchingWithInterface(Type? handlerType, Type handlerInterface)\n    {\n        if (handlerType == null || handlerInterface == null)\n        {\n            return false;\n        }\n\n        if (handlerType.IsInterface)\n        {\n            if (handlerType.GenericTypeArguments.SequenceEqual(handlerInterface.GenericTypeArguments))\n            {\n                return true;\n            }\n        }\n        else\n        {\n            return IsMatchingWithInterface(handlerType.GetInterface(handlerInterface.Name), handlerInterface);\n        }\n\n        return false;\n    }\n\n    private static void AddConcretionsThatCouldBeClosed(Type @interface, List<Type> concretions, IServiceCollection services)\n    {\n        foreach (var type in concretions\n                     .Where(x => x.IsOpenGeneric() && x.CouldCloseTo(@interface)))\n        {\n            try\n            {\n                services.TryAddTransient(@interface, type.MakeGenericType(@interface.GenericTypeArguments));\n            }\n            catch (Exception)\n            {\n            }\n        }\n    }\n\n    private static (Type Service, Type Implementation) GetConcreteRegistrationTypes(Type openRequestHandlerInterface, Type concreteGenericTRequest, Type openRequestHandlerImplementation)\n    {\n        var closingTypes = concreteGenericTRequest.GetGenericArguments();\n\n        var concreteTResponse = concreteGenericTRequest.GetInterfaces()\n            .FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IRequest<>))\n            ?.GetGenericArguments()\n            .FirstOrDefault();\n\n        var typeDefinition = openRequestHandlerInterface.GetGenericTypeDefinition();\n\n        var serviceType = concreteTResponse != null ?\n            typeDefinition.MakeGenericType(concreteGenericTRequest, concreteTResponse) :\n            typeDefinition.MakeGenericType(concreteGenericTRequest);\n\n        return (serviceType, openRequestHandlerImplementation.MakeGenericType(closingTypes));\n    }\n\n    private static List<Type>? GetConcreteRequestTypes(Type openRequestHandlerInterface, Type openRequestHandlerImplementation, IEnumerable<Assembly> assembliesToScan, CancellationToken cancellationToken)\n    {\n        //request generic type constraints       \n        var constraintsForEachParameter = openRequestHandlerImplementation\n            .GetGenericArguments()\n            .Select(x => x.GetGenericParameterConstraints())\n            .ToList();\n\n        var typesThatCanCloseForEachParameter = constraintsForEachParameter\n            .Select(constraints => assembliesToScan\n                .SelectMany(assembly => assembly.GetLoadableDefinedTypes())\n                .Where(type => type.IsClass && !type.IsAbstract && constraints.All(constraint => constraint.IsAssignableFrom(type))).ToList()\n            ).ToList();\n\n        var requestType = openRequestHandlerInterface.GenericTypeArguments.First();\n\n        if (requestType.IsGenericParameter)\n            return null;\n\n        var requestGenericTypeDefinition = requestType.GetGenericTypeDefinition();\n              \n        var combinations = GenerateCombinations(requestType, typesThatCanCloseForEachParameter, 0, cancellationToken);\n\n        return combinations.Select(types => requestGenericTypeDefinition.MakeGenericType(types.ToArray())).ToList();\n    }\n\n    // Method to generate combinations recursively\n    public static List<List<Type>> GenerateCombinations(Type requestType, List<List<Type>> lists, int depth = 0, CancellationToken cancellationToken = default)\n    {\n        if (depth == 0)\n        {\n            // Initial checks\n            if (MaxGenericTypeParameters > 0 && lists.Count > MaxGenericTypeParameters)\n                throw new ArgumentException($\"Error registering the generic type: {requestType.FullName}. The number of generic type parameters exceeds the maximum allowed ({MaxGenericTypeParameters}).\");\n\n            foreach (var list in lists)\n            {\n                if (MaxTypesClosing > 0 && list.Count > MaxTypesClosing)\n                    throw new ArgumentException($\"Error registering the generic type: {requestType.FullName}. One of the generic type parameter's count of types that can close exceeds the maximum length allowed ({MaxTypesClosing}).\");\n            }\n\n            // Calculate the total number of combinations\n            long totalCombinations = 1;\n            foreach (var list in lists)\n            {\n                totalCombinations *= list.Count;\n                if (MaxGenericTypeParameters > 0 && totalCombinations > MaxGenericTypeRegistrations)\n                    throw new ArgumentException($\"Error registering the generic type: {requestType.FullName}. The total number of generic type registrations exceeds the maximum allowed ({MaxGenericTypeRegistrations}).\");\n            }\n        }\n\n        if (depth >= lists.Count)\n            return new List<List<Type>> { new List<Type>() };\n       \n        cancellationToken.ThrowIfCancellationRequested();\n\n        var currentList = lists[depth];\n        var childCombinations = GenerateCombinations(requestType, lists, depth + 1, cancellationToken);\n        var combinations = new List<List<Type>>();\n\n        foreach (var item in currentList)\n        {\n            foreach (var childCombination in childCombinations)\n            {\n                var currentCombination = new List<Type> { item };\n                currentCombination.AddRange(childCombination);\n                combinations.Add(currentCombination);\n            }\n        }\n\n        return combinations;\n    }\n\n    private static void AddAllConcretionsThatClose(Type openRequestInterface, List<Type> concretions, IServiceCollection services, IEnumerable<Assembly> assembliesToScan, CancellationToken cancellationToken)\n    {\n        foreach (var concretion in concretions)\n        {   \n            var concreteRequests = GetConcreteRequestTypes(openRequestInterface, concretion, assembliesToScan, cancellationToken);\n\n            if (concreteRequests is null)\n                continue;\n\n            var registrationTypes = concreteRequests\n                .Select(concreteRequest => GetConcreteRegistrationTypes(openRequestInterface, concreteRequest, concretion));\n\n            foreach (var (Service, Implementation) in registrationTypes)\n            {\n                cancellationToken.ThrowIfCancellationRequested();\n                services.AddTransient(Service, Implementation);\n            }\n        }\n    }\n\n    internal static bool CouldCloseTo(this Type openConcretion, Type closedInterface)\n    {\n        var openInterface = closedInterface.GetGenericTypeDefinition();\n        var arguments = closedInterface.GenericTypeArguments;\n\n        var concreteArguments = openConcretion.GenericTypeArguments;\n        return arguments.Length == concreteArguments.Length && openConcretion.CanBeCastTo(openInterface);\n    }\n\n    private static bool CanBeCastTo(this Type pluggedType, Type pluginType)\n    {\n        if (pluggedType == null) return false;\n\n        if (pluggedType == pluginType) return true;\n\n        return pluginType.IsAssignableFrom(pluggedType);\n    }\n\n    private static bool IsOpenGeneric(this Type type)\n    {\n        return type.IsGenericTypeDefinition || type.ContainsGenericParameters;\n    }\n\n    internal static IEnumerable<Type> FindInterfacesThatClose(this Type pluggedType, Type templateType)\n    {\n        return FindInterfacesThatClosesCore(pluggedType, templateType).Distinct();\n    }\n\n    private static IEnumerable<Type> FindInterfacesThatClosesCore(Type pluggedType, Type templateType)\n    {\n        if (pluggedType == null) yield break;\n\n        if (!pluggedType.IsConcrete()) yield break;\n\n        if (templateType.IsInterface)\n        {\n            foreach (\n                var interfaceType in\n                pluggedType.GetInterfaces()\n                    .Where(type => type.IsGenericType && (type.GetGenericTypeDefinition() == templateType)))\n            {\n                yield return interfaceType;\n            }\n        }\n        else if (pluggedType.BaseType!.IsGenericType &&\n                 (pluggedType.BaseType!.GetGenericTypeDefinition() == templateType))\n        {\n            yield return pluggedType.BaseType!;\n        }\n\n        if (pluggedType.BaseType == typeof(object)) yield break;\n\n        foreach (var interfaceType in FindInterfacesThatClosesCore(pluggedType.BaseType!, templateType))\n        {\n            yield return interfaceType;\n        }\n    }\n\n    private static bool IsConcrete(this Type type)\n    {\n        return !type.IsAbstract && !type.IsInterface;\n    }\n\n    private static void Fill<T>(this IList<T> list, T value)\n    {\n        if (list.Contains(value)) return;\n        list.Add(value);\n    }\n\n    private static IEnumerable<Type> GetLoadableDefinedTypes(this Assembly assembly)\n    {\n        try\n        {\n            return assembly.DefinedTypes;\n        }\n        catch (ReflectionTypeLoadException ex)\n        {\n            return ex.Types.OfType<Type>();\n        }\n    }\n\n    private static bool HasNestedGenericResponseType(Type openBehaviorType)\n    {\n        var iface = openBehaviorType.GetInterfaces()\n            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPipelineBehavior<,>));\n        if (iface == null) return false;\n        return iface.GetGenericArguments()[1].IsGenericType;\n    }\n\n    private static bool TryMatchType(Type pattern, Type concrete, Dictionary<Type, Type> bindings)\n    {\n        if (pattern.IsGenericParameter)\n        {\n            if (bindings.TryGetValue(pattern, out var existing)) return existing == concrete;\n            bindings[pattern] = concrete;\n            return true;\n        }\n        if (pattern.IsGenericType && concrete.IsGenericType)\n        {\n            if (pattern.GetGenericTypeDefinition() != concrete.GetGenericTypeDefinition()) return false;\n            var pArgs = pattern.GetGenericArguments();\n            var cArgs = concrete.GetGenericArguments();\n            if (pArgs.Length != cArgs.Length) return false;\n            return pArgs.Zip(cArgs, (p, c) => TryMatchType(p, c, bindings)).All(x => x);\n        }\n        return pattern == concrete;\n    }\n\n    private static void RegisterClosedBehaviorsFromAssemblies(\n        Type openBehaviorType, IServiceCollection services,\n        IEnumerable<Assembly> assemblies, ServiceLifetime lifetime)\n    {\n        var iface = openBehaviorType.GetInterfaces()\n            .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IPipelineBehavior<,>));\n        if (iface == null) return;\n\n        var requestPattern  = iface.GetGenericArguments()[0];\n        var responsePattern = iface.GetGenericArguments()[1];\n        var behaviorParams  = openBehaviorType.GetGenericArguments();\n\n        var requests = assemblies\n            .SelectMany(a => a.GetLoadableDefinedTypes())\n            .Where(t => t.IsConcrete() && !t.ContainsGenericParameters)\n            .SelectMany(t => t.GetInterfaces()\n                .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRequest<>))\n                .Select(i => (RequestType: (Type)t, ResponseType: i.GetGenericArguments()[0])));\n\n        foreach (var (requestType, responseType) in requests)\n        {\n            var bindings = new Dictionary<Type, Type>();\n            if (!TryMatchType(requestPattern,  requestType,  bindings)) continue;\n            if (!TryMatchType(responsePattern, responseType, bindings)) continue;\n            if (!behaviorParams.All(tp => bindings.ContainsKey(tp)))   continue;\n            try\n            {\n                var closingArgs    = behaviorParams.Select(tp => bindings[tp]).ToArray();\n                var closedBehavior = openBehaviorType.MakeGenericType(closingArgs);\n                var closedService  = typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType);\n                services.TryAddEnumerable(new ServiceDescriptor(closedService, closedBehavior, lifetime));\n            }\n            catch (Exception) { /* ignore invalid type constructions */ }\n        }\n    }\n\n    public static void AddRequiredServices(IServiceCollection services, MediatRServiceConfiguration serviceConfiguration)\n    {\n        // Use TryAdd, so any existing ServiceFactory/IMediator registration doesn't get overridden\n        services.TryAdd(new ServiceDescriptor(typeof(IMediator), serviceConfiguration.MediatorImplementationType, serviceConfiguration.Lifetime));\n        services.TryAdd(new ServiceDescriptor(typeof(ISender), sp => sp.GetRequiredService<IMediator>(), serviceConfiguration.Lifetime));\n        services.TryAdd(new ServiceDescriptor(typeof(IPublisher), sp => sp.GetRequiredService<IMediator>(), serviceConfiguration.Lifetime));\n\n        MediatRServiceCollectionExtensions.LicenseChecked = false;\n        \n        services.TryAddSingleton(serviceConfiguration);\n        services.TryAddSingleton<LicenseAccessor>(static sp =>\n        {\n            var loggerFactory = sp.GetService<ILoggerFactory>()\n                ?? throw new InvalidOperationException(\n                    \"MediatR requires ILoggerFactory to be registered. \" +\n                    \"Call services.AddLogging() before services.AddMediatR().\");\n            var config = sp.GetService<MediatRServiceConfiguration>();\n            return config != null\n                ? new LicenseAccessor(config, loggerFactory)\n                : new LicenseAccessor(loggerFactory);\n        });\n        services.TryAddSingleton<LicenseValidator>(static sp =>\n        {\n            var loggerFactory = sp.GetService<ILoggerFactory>()\n                ?? throw new InvalidOperationException(\n                    \"MediatR requires ILoggerFactory to be registered. \" +\n                    \"Call services.AddLogging() before services.AddMediatR().\");\n            return new LicenseValidator(loggerFactory);\n        });\n\n        var notificationPublisherServiceDescriptor = serviceConfiguration.NotificationPublisherType != null\n            ? new ServiceDescriptor(typeof(INotificationPublisher), serviceConfiguration.NotificationPublisherType, serviceConfiguration.Lifetime)\n            : new ServiceDescriptor(typeof(INotificationPublisher), serviceConfiguration.NotificationPublisher);\n\n        services.TryAdd(notificationPublisherServiceDescriptor);\n\n        // Register pre processors, then post processors, then behaviors\n        if (serviceConfiguration.RequestExceptionActionProcessorStrategy == RequestExceptionActionProcessorStrategy.ApplyForUnhandledExceptions)\n        {\n            RegisterBehaviorIfImplementationsExist(services, typeof(RequestExceptionActionProcessorBehavior<,>), typeof(IRequestExceptionAction<,>));\n            RegisterBehaviorIfImplementationsExist(services, typeof(RequestExceptionProcessorBehavior<,>), typeof(IRequestExceptionHandler<,,>));\n        }\n        else\n        {\n            RegisterBehaviorIfImplementationsExist(services, typeof(RequestExceptionProcessorBehavior<,>), typeof(IRequestExceptionHandler<,,>));\n            RegisterBehaviorIfImplementationsExist(services, typeof(RequestExceptionActionProcessorBehavior<,>), typeof(IRequestExceptionAction<,>));\n        }\n\n        if (serviceConfiguration.RequestPreProcessorsToRegister.Any())\n        {\n            services.TryAddEnumerable(new ServiceDescriptor(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>), ServiceLifetime.Transient));\n            services.TryAddEnumerable(serviceConfiguration.RequestPreProcessorsToRegister);\n        }\n\n        if (serviceConfiguration.RequestPostProcessorsToRegister.Any())\n        {\n            services.TryAddEnumerable(new ServiceDescriptor(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>), ServiceLifetime.Transient));\n            services.TryAddEnumerable(serviceConfiguration.RequestPostProcessorsToRegister);\n        }\n\n        foreach (var serviceDescriptor in serviceConfiguration.BehaviorsToRegister)\n        {\n            services.TryAddEnumerable(serviceDescriptor);\n\n            // For open behaviors whose TResponse is a nested generic (e.g. List<T>, Result<T>),\n            // the DI container cannot close them correctly via positional mapping.\n            // Register explicitly-closed versions by scanning assemblies for matching request types.\n            if (serviceDescriptor.ImplementationType != null\n                && serviceDescriptor.ServiceType == typeof(IPipelineBehavior<,>)\n                && serviceDescriptor.ImplementationType.IsOpenGeneric()\n                && HasNestedGenericResponseType(serviceDescriptor.ImplementationType))\n            {\n                RegisterClosedBehaviorsFromAssemblies(\n                    serviceDescriptor.ImplementationType,\n                    services,\n                    serviceConfiguration.AssembliesToRegister,\n                    serviceDescriptor.Lifetime);\n            }\n        }\n\n        foreach (var serviceDescriptor in serviceConfiguration.StreamBehaviorsToRegister)\n        {\n            services.TryAddEnumerable(serviceDescriptor);\n        }\n    }\n\n    private static void RegisterBehaviorIfImplementationsExist(IServiceCollection services, Type behaviorType, Type subBehaviorType)\n    {\n        var hasAnyRegistrationsOfSubBehaviorType = services\n            .Where(service => !service.IsKeyedService)\n            .Select(service => service.ImplementationType)\n            .OfType<Type>()\n            .SelectMany(type => type.GetInterfaces())\n            .Where(type => type.IsGenericType)\n            .Select(type => type.GetGenericTypeDefinition())\n            .Any(type => type == subBehaviorType);\n\n        if (hasAnyRegistrationsOfSubBehaviorType)\n        {\n            services.TryAddEnumerable(new ServiceDescriptor(typeof(IPipelineBehavior<,>), behaviorType, ServiceLifetime.Transient));\n        }\n    }\n}\n"
  },
  {
    "path": "src/MediatR/TypeForwardings.cs",
    "content": "﻿using System.Runtime.CompilerServices;\nusing MediatR;\n\n[assembly: TypeForwardedTo(typeof(IBaseRequest))]\n[assembly: TypeForwardedTo(typeof(IRequest<>))]\n[assembly: TypeForwardedTo(typeof(IRequest))]\n[assembly: TypeForwardedTo(typeof(INotification))]\n[assembly: TypeForwardedTo(typeof(Unit))]"
  },
  {
    "path": "src/MediatR/Wrappers/NotificationHandlerWrapper.cs",
    "content": "namespace MediatR.Wrappers;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\n\npublic abstract class NotificationHandlerWrapper\n{\n    public abstract Task Handle(INotification notification, IServiceProvider serviceFactory,\n        Func<IEnumerable<NotificationHandlerExecutor>, INotification, CancellationToken, Task> publish,\n        CancellationToken cancellationToken);\n}\n\npublic class NotificationHandlerWrapperImpl<TNotification> : NotificationHandlerWrapper\n    where TNotification : INotification\n{\n    public override Task Handle(INotification notification, IServiceProvider serviceFactory,\n        Func<IEnumerable<NotificationHandlerExecutor>, INotification, CancellationToken, Task> publish,\n        CancellationToken cancellationToken)\n    {\n        var handlers = serviceFactory\n            .GetServices<INotificationHandler<TNotification>>()\n            .GroupBy(static x => x.GetType())\n            .Select(static g => g.First())\n            .Select(static x => new NotificationHandlerExecutor(x, (theNotification, theToken) => x.Handle((TNotification)theNotification, theToken)));\n\n        return publish(handlers, notification, cancellationToken);\n    }\n}"
  },
  {
    "path": "src/MediatR/Wrappers/RequestHandlerWrapper.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Wrappers;\n\npublic abstract class RequestHandlerBase\n{\n    public abstract Task<object?> Handle(object request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken);\n}\n\npublic abstract class RequestHandlerWrapper<TResponse> : RequestHandlerBase\n{\n    public abstract Task<TResponse> Handle(IRequest<TResponse> request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken);\n}\n\npublic abstract class RequestHandlerWrapper : RequestHandlerBase\n{\n    public abstract Task<Unit> Handle(IRequest request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken);\n}\n\npublic class RequestHandlerWrapperImpl<TRequest, TResponse> : RequestHandlerWrapper<TResponse>\n    where TRequest : IRequest<TResponse>\n{\n    public override async Task<object?> Handle(object request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken) =>\n        await Handle((IRequest<TResponse>) request, serviceProvider, cancellationToken).ConfigureAwait(false);\n\n    public override Task<TResponse> Handle(IRequest<TResponse> request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken)\n    {\n        Task<TResponse> Handler(CancellationToken t = default) => serviceProvider.GetRequiredService<IRequestHandler<TRequest, TResponse>>()\n            .Handle((TRequest) request, t == default ? cancellationToken : t);\n\n        return serviceProvider\n            .GetServices<IPipelineBehavior<TRequest, TResponse>>()\n            .Reverse()\n            .Aggregate((RequestHandlerDelegate<TResponse>) Handler,\n                (next, pipeline) => (t) => pipeline.Handle((TRequest) request, next, t == default ? cancellationToken : t))();\n    }\n}\n\npublic class RequestHandlerWrapperImpl<TRequest> : RequestHandlerWrapper\n    where TRequest : IRequest\n{\n    public override async Task<object?> Handle(object request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken) =>\n        await Handle((IRequest) request, serviceProvider, cancellationToken).ConfigureAwait(false);\n\n    public override Task<Unit> Handle(IRequest request, IServiceProvider serviceProvider,\n        CancellationToken cancellationToken)\n    {\n        async Task<Unit> Handler(CancellationToken t = default)\n        {\n            await serviceProvider.GetRequiredService<IRequestHandler<TRequest>>()\n                .Handle((TRequest) request, t == default ? cancellationToken : t);\n\n            return Unit.Value;\n        }\n\n        return serviceProvider\n            .GetServices<IPipelineBehavior<TRequest, Unit>>()\n            .Reverse()\n            .Aggregate((RequestHandlerDelegate<Unit>) Handler,\n                (next, pipeline) => (t) => pipeline.Handle((TRequest) request, next, t == default ? cancellationToken : t))();\n    }\n}"
  },
  {
    "path": "src/MediatR/Wrappers/StreamRequestHandlerWrapper.cs",
    "content": "using System;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Wrappers;\n\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Runtime.CompilerServices;\nusing System.Threading;\nusing System.Threading.Tasks;\n\ninternal abstract class StreamRequestHandlerBase\n{\n    public abstract IAsyncEnumerable<object?> Handle(object request, IServiceProvider serviceProvider, CancellationToken cancellationToken);\n}\n\ninternal abstract class StreamRequestHandlerWrapper<TResponse> : StreamRequestHandlerBase\n{\n    public abstract IAsyncEnumerable<TResponse> Handle(\n        IStreamRequest<TResponse> request, \n        IServiceProvider serviceProvider,\n        CancellationToken cancellationToken);\n}\n\ninternal class StreamRequestHandlerWrapperImpl<TRequest, TResponse> \n    : StreamRequestHandlerWrapper<TResponse>\n    where TRequest : IStreamRequest<TResponse>\n{\n    public override async IAsyncEnumerable<object?> Handle(object request, IServiceProvider serviceProvider, [EnumeratorCancellation] CancellationToken cancellationToken)\n    {\n        await foreach (var item in Handle((IStreamRequest<TResponse>) request, serviceProvider, cancellationToken))\n        {\n            yield return item;\n        }\n    }\n\n    public override async IAsyncEnumerable<TResponse> Handle(IStreamRequest<TResponse> request, \n        IServiceProvider serviceProvider, \n        [EnumeratorCancellation] CancellationToken cancellationToken)\n    {\n        IAsyncEnumerable<TResponse> Handler() => serviceProvider\n            .GetRequiredService<IStreamRequestHandler<TRequest, TResponse>>()\n            .Handle((TRequest) request, cancellationToken);\n\n        var items = serviceProvider\n            .GetServices<IStreamPipelineBehavior<TRequest, TResponse>>()\n            .Reverse()\n            .Aggregate(\n                (StreamHandlerDelegate<TResponse>) Handler, \n                (next, pipeline) => () => pipeline.Handle(\n                    (TRequest) request, \n                    () => NextWrapper(next(), cancellationToken),\n                    cancellationToken\n                )\n            )();\n\n        await foreach ( var item in items.WithCancellation(cancellationToken) )\n        {\n            yield return item;\n        }\n    }\n\n\n    private static async IAsyncEnumerable<T> NextWrapper<T>(\n        IAsyncEnumerable<T> items,\n        [EnumeratorCancellation] CancellationToken cancellationToken)\n    {\n        var cancellable = items\n            .WithCancellation(cancellationToken)\n            .ConfigureAwait(false);\n        await foreach (var item in cancellable)\n        {\n            yield return item;\n        }\n    }\n\n}"
  },
  {
    "path": "src/MediatR/license.txt",
    "content": "By accessing code under the [Lucky Penny Software GitHub Organization](https://github.com/LuckyPennySoftware) (Lucky Penny Software) here, you are agreeing to the following licensing terms.\nIf you do not agree to these terms, do not access Lucky Penny Software code.\n\nYour license to Lucky Penny Software source code and/or binaries is governed by the Reciprocal Public License 1.5 (RPL1.5) license as described here: \n\nhttps://opensource.org/license/rpl-1-5/\n\nIf you do not wish to release the source of software you build using Lucky Penny Software source code and/or binaries under the terms above, you may use Lucky Penny Software source code and/or binaries under the License Agreement described here:\n\nhttps://luckypennysoftware.com/license"
  },
  {
    "path": "src/MediatR.Contracts/INotification.cs",
    "content": "namespace MediatR;\n\n/// <summary>\n/// Marker interface to represent a notification\n/// </summary>\npublic interface INotification { }"
  },
  {
    "path": "src/MediatR.Contracts/IRequest.cs",
    "content": "namespace MediatR;\n\n/// <summary>\n/// Marker interface to represent a request with a void response\n/// </summary>\npublic interface IRequest : IBaseRequest { }\n\n/// <summary>\n/// Marker interface to represent a request with a response\n/// </summary>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic interface IRequest<out TResponse> : IBaseRequest { }\n\n/// <summary>\n/// Allows for generic type constraints of objects implementing IRequest or IRequest{TResponse}\n/// </summary>\npublic interface IBaseRequest { }"
  },
  {
    "path": "src/MediatR.Contracts/IStreamRequest.cs",
    "content": "namespace MediatR;\n\n/// <summary>\n/// Marker interface to represent a request with a streaming response\n/// </summary>\n/// <typeparam name=\"TResponse\">Response type</typeparam>\npublic interface IStreamRequest<out TResponse> { }\n"
  },
  {
    "path": "src/MediatR.Contracts/MediatR.Contracts.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <Nullable>enable</Nullable>\n    <Authors>Jimmy Bogard</Authors>\n    <Description>Contracts package for requests, responses, and notifications</Description>\n    <Copyright>Copyright Jimmy Bogard</Copyright>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <Features>strict</Features>\n    <PackageTags>mediator;request;response;queries;commands;notifications</PackageTags>\n    <SignAssembly>true</SignAssembly>\n    <AssemblyOriginatorKeyFile>..\\..\\MediatR.snk</AssemblyOriginatorKeyFile>\n    <GenerateDocumentationFile>true</GenerateDocumentationFile>\n    <PackageIcon>gradient_128x128.png</PackageIcon>\n    <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>\n    <PublishRepositoryUrl>true</PublishRepositoryUrl>\n    <IncludeSymbols>true</IncludeSymbols>\n    <SymbolPackageFormat>snupkg</SymbolPackageFormat>\n    <EmbedUntrackedSources>true</EmbedUntrackedSources>\n    <Deterministic>true</Deterministic>\n    <Version>2.0.1</Version>\n    <RootNamespace>MediatR</RootNamespace>\n\n  </PropertyGroup>\n\n  <ItemGroup>\n    <None Include=\"..\\..\\assets\\logo\\gradient_128x128.png\" Pack=\"true\" PackagePath=\"\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"8.0.0\" PrivateAssets=\"All\" />\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/MediatR.Contracts/Unit.cs",
    "content": "﻿namespace MediatR;\n\nusing System;\nusing System.Threading.Tasks;\n\n/// <summary>\n/// Represents a void type, since <see cref=\"System.Void\"/> is not a valid return type in C#.\n/// </summary>\npublic readonly struct Unit : IEquatable<Unit>, IComparable<Unit>, IComparable\n{\n    private static readonly Unit _value = new();\n\n    /// <summary>\n    /// Default and only value of the <see cref=\"Unit\"/> type.\n    /// </summary>\n    public static ref readonly Unit Value => ref _value;\n\n    /// <summary>\n    /// Task from a <see cref=\"Unit\"/> type.\n    /// </summary>\n    public static Task<Unit> Task { get; } = System.Threading.Tasks.Task.FromResult(_value);\n\n    /// <summary>\n    /// Compares the current object with another object of the same type.\n    /// </summary>\n    /// <param name=\"other\">An object to compare with this object.</param>\n    /// <returns>\n    /// A value that indicates the relative order of the objects being compared.\n    /// The return value has the following meanings:\n    ///  - Less than zero: This object is less than the <paramref name=\"other\" /> parameter.\n    ///  - Zero: This object is equal to <paramref name=\"other\" />.\n    ///  - Greater than zero: This object is greater than <paramref name=\"other\" />.\n    /// </returns>\n    public int CompareTo(Unit other) => 0;\n\n    /// <summary>\n    /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.\n    /// </summary>\n    /// <param name=\"obj\">An object to compare with this instance.</param>\n    /// <returns>\n    /// A value that indicates the relative order of the objects being compared.\n    /// The return value has these meanings:\n    ///  - Less than zero: This instance precedes <paramref name=\"obj\" /> in the sort order.\n    ///  - Zero: This instance occurs in the same position in the sort order as <paramref name=\"obj\" />.\n    ///  - Greater than zero: This instance follows <paramref name=\"obj\" /> in the sort order.\n    /// </returns>\n    int IComparable.CompareTo(object? obj) => 0;\n\n    /// <summary>\n    /// Returns a hash code for this instance.\n    /// </summary>\n    /// <returns>\n    /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.\n    /// </returns>\n    public override int GetHashCode() => 0;\n\n    /// <summary>\n    /// Determines whether the current object is equal to another object of the same type.\n    /// </summary>\n    /// <param name=\"other\">An object to compare with this object.</param>\n    /// <returns>\n    /// <c>true</c> if the current object is equal to the <paramref name=\"other\" /> parameter; otherwise, <c>false</c>.\n    /// </returns>\n    public bool Equals(Unit other) => true;\n\n    /// <summary>\n    /// Determines whether the specified <see cref=\"System.Object\" /> is equal to this instance.\n    /// </summary>\n    /// <param name=\"obj\">The object to compare with the current instance.</param>\n    /// <returns>\n    /// <c>true</c> if the specified <see cref=\"System.Object\" /> is equal to this instance; otherwise, <c>false</c>.\n    /// </returns>\n    public override bool Equals(object? obj) => obj is Unit;\n\n    /// <summary>\n    /// Determines whether the <paramref name=\"first\"/> object is equal to the <paramref name=\"second\"/> object.\n    /// </summary>\n    /// <param name=\"first\">The first object.</param>\n    /// <param name=\"second\">The second object.</param>\n    /// <c>true</c> if the <paramref name=\"first\"/> object is equal to the <paramref name=\"second\" /> object; otherwise, <c>false</c>.\n    public static bool operator ==(Unit first, Unit second) => true;\n\n    /// <summary>\n    /// Determines whether the <paramref name=\"first\"/> object is not equal to the <paramref name=\"second\"/> object.\n    /// </summary>\n    /// <param name=\"first\">The first object.</param>\n    /// <param name=\"second\">The second object.</param>\n    /// <c>true</c> if the <paramref name=\"first\"/> object is not equal to the <paramref name=\"second\" /> object; otherwise, <c>false</c>.\n    public static bool operator !=(Unit first, Unit second) => false;\n\n    /// <summary>\n    /// Returns a <see cref=\"System.String\" /> that represents this instance.\n    /// </summary>\n    /// <returns>A <see cref=\"System.String\" /> that represents this instance.</returns>\n    public override string ToString() => \"()\";\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/Benchmarks.cs",
    "content": "using System.IO;\nusing System.Threading.Tasks;\nusing BenchmarkDotNet.Attributes;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Benchmarks\n{\n    [DotTraceDiagnoser]\n    public class Benchmarks\n    {\n        private IMediator _mediator;\n        private readonly Ping _request = new Ping {Message = \"Hello World\"};\n        private readonly Pinged _notification = new Pinged();\n\n        [GlobalSetup]\n        public void GlobalSetup()\n        {\n            var services = new ServiceCollection();\n\n            services.AddSingleton(TextWriter.Null);\n\n            services.AddMediatR(cfg =>\n            {\n                cfg.RegisterServicesFromAssemblyContaining(typeof(Ping));\n                cfg.AddOpenBehavior(typeof(GenericPipelineBehavior<,>));\n            });\n\n            var provider = services.BuildServiceProvider();\n\n            _mediator = provider.GetRequiredService<IMediator>();\n        }\n\n        [Benchmark]\n        public Task SendingRequests()\n        {\n            return _mediator.Send(_request);\n        }\n\n        [Benchmark]\n        public Task PublishingNotifications()\n        {\n            return _mediator.Publish(_notification);\n        }\n    }\n}\n"
  },
  {
    "path": "test/MediatR.Benchmarks/DotTraceDiagnoser.cs",
    "content": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.IO;\nusing System.Linq;\nusing BenchmarkDotNet.Analysers;\nusing BenchmarkDotNet.Configs;\nusing BenchmarkDotNet.Diagnosers;\nusing BenchmarkDotNet.Engines;\nusing BenchmarkDotNet.Exporters;\nusing BenchmarkDotNet.Loggers;\nusing BenchmarkDotNet.Reports;\nusing BenchmarkDotNet.Running;\nusing BenchmarkDotNet.Validators;\n\nnamespace MediatR.Benchmarks\n{\n    internal sealed class DotTraceDiagnoserAttribute : Attribute, IConfigSource\n    {\n        public DotTraceDiagnoserAttribute()\n        {\n            var manualConfig = ManualConfig.CreateEmpty();\n            manualConfig.AddDiagnoser(new DotTraceDiagnoser());\n            Config = manualConfig;\n        }\n\n        public IConfig Config { get; }\n    }\n\n    internal sealed class DotTraceDiagnoser : IDiagnoser\n    {\n        private const string DotTraceExecutableNotFoundErrorMessage = \"dotTrace executable was not found. \" +\n            \"Make sure it is part of the PATH or install JetBrains.dotTrace.GlobalTools\";\n\n        private readonly string _saveLocation;\n\n        public DotTraceDiagnoser()\n        {\n            _saveLocation = $\"C:\\\\temp\\\\MediatR\\\\{DateTimeOffset.Now.UtcDateTime:yyyy-MM-dd-HH_mm_ss}.bench.dtp\";\n        }\n\n        /// <inheritdoc />\n        public RunMode GetRunMode(BenchmarkCase benchmarkCase) => RunMode.ExtraRun;\n\n        /// <inheritdoc />\n        public void Handle(HostSignal signal, DiagnoserActionParameters parameters)\n        {\n            if (signal != HostSignal.BeforeActualRun)\n            {\n                return;\n            }\n\n            try\n            {\n                if (!CanRunDotTrace())\n                {\n                    Console.WriteLine(DotTraceExecutableNotFoundErrorMessage);\n                    return;\n                }\n\n                // The directory must exist or an error is thrown by dotTrace.\n                Directory.CreateDirectory(_saveLocation);\n                RunDotTrace(parameters);\n            }\n            catch (Exception e)\n            {\n                Console.Error.WriteLine(e.ToString());\n                throw;\n            }\n        }\n\n        private void RunDotTrace(DiagnoserActionParameters parameters)\n        {\n            var dotTrace = new Process\n            {\n                StartInfo = PrepareProcessStartInfo(parameters)\n            };\n            dotTrace.ErrorDataReceived += (sender, eventArgs) => Console.Error.WriteLine(eventArgs.Data);\n            dotTrace.OutputDataReceived += (sender, eventArgs) => Console.WriteLine(eventArgs.Data);\n            dotTrace.Start();\n            dotTrace.BeginErrorReadLine();\n            dotTrace.BeginOutputReadLine();\n            dotTrace.Exited += (sender, args) => dotTrace.Dispose();\n        }\n\n        private ProcessStartInfo PrepareProcessStartInfo(DiagnoserActionParameters parameters)\n        {\n            return new ProcessStartInfo(\n                \"dottrace\",\n                $\"attach {parameters.Process.Id} --save-to={_saveLocation}\")\n            {\n                RedirectStandardError = true,\n                RedirectStandardOutput = true,\n                WindowStyle = ProcessWindowStyle.Hidden,\n                UseShellExecute = false,\n                CreateNoWindow = true,\n            };\n        }\n\n        /// <inheritdoc />\n        public IEnumerable<Metric> ProcessResults(DiagnoserResults results) => Enumerable.Empty<Metric>();\n\n        /// <inheritdoc />\n        public void DisplayResults(ILogger logger) { }\n\n        /// <inheritdoc />\n        public IEnumerable<ValidationError> Validate(ValidationParameters validationParameters) =>\n            Enumerable.Empty<ValidationError>();\n\n        /// <inheritdoc />\n        public IEnumerable<string> Ids => new[] { nameof(DotTraceDiagnoser) };\n\n        /// <inheritdoc />\n        public IEnumerable<IExporter> Exporters => Enumerable.Empty<IExporter>();\n\n        public IEnumerable<IAnalyser> Analysers { get; } = Enumerable.Empty<IAnalyser>();\n\n        private static bool CanRunDotTrace()\n        {\n            try\n            {\n                var startInfo = new ProcessStartInfo(\"dottrace\")\n                {\n                    RedirectStandardError = true,\n                    RedirectStandardOutput = true,\n                    UseShellExecute = false,\n                    CreateNoWindow = true,\n                };\n\n                using var process = new Process { StartInfo = startInfo };\n                process.Start();\n                process.WaitForExit();\n\n                return true;\n            }\n            catch (Exception)\n            {\n                return false;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/MediatR.Benchmarks/GenericPipelineBehavior.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Benchmarks\n{\n    public class GenericPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly TextWriter _writer;\n\n        public GenericPipelineBehavior(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            await _writer.WriteLineAsync(\"-- Handling Request\");\n            var response = await next();\n            await _writer.WriteLineAsync(\"-- Finished Request\");\n            return response;\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/GenericRequestPostProcessor.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Benchmarks\n{\n    public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly TextWriter _writer;\n\n        public GenericRequestPostProcessor(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        public Task Process(TRequest request, TResponse response, CancellationToken cancellationToken)\n        {\n            return _writer.WriteLineAsync(\"- All Done\");\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/GenericRequestPreProcessor.cs",
    "content": "using System.IO;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\n\nnamespace MediatR.Benchmarks\n{\n    public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest>\n        where TRequest : notnull\n    {\n        private readonly TextWriter _writer;\n\n        public GenericRequestPreProcessor(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        public Task Process(TRequest request, CancellationToken cancellationToken)\n        {\n            return _writer.WriteLineAsync(\"- Starting Up\");\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/MediatR.Benchmarks.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n  <PropertyGroup>\n    <TargetFramework>net10.0</TargetFramework>\n    <OutputType>Exe</OutputType>\n  </PropertyGroup>\n  <PropertyGroup>\n    <PlatformTarget>AnyCPU</PlatformTarget>\n    <DebugType>portable</DebugType>\n    <DebugSymbols>true</DebugSymbols>\n    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\n    <Optimize>true</Optimize>\n    <Configuration>Release</Configuration>\n  </PropertyGroup>\n  <ItemGroup>\n    <PackageReference Include=\"BenchmarkDotNet\" Version=\"0.13.10\" />\n    <PackageReference Include=\"BenchmarkDotNet.Diagnostics.Windows\" Version=\"0.13.10\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\MediatR\\MediatR.csproj\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "test/MediatR.Benchmarks/Ping.cs",
    "content": "using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Benchmarks\n{\n    public class Ping : IRequest\n    {\n        public string Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping>\n    {\n        public Task Handle(Ping request, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/Pinged.cs",
    "content": "using System.Threading;\nusing System.Threading.Tasks;\n\nnamespace MediatR.Benchmarks\n{\n    public class Pinged : INotification\n    {\n    }\n\n    public class PingedHandler : INotificationHandler<Pinged>\n    {\n        public Task Handle(Pinged notification, CancellationToken cancellationToken)\n        {\n            return Task.CompletedTask;\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.Benchmarks/Program.cs",
    "content": "using BenchmarkDotNet.Running;\n\nnamespace MediatR.Benchmarks\n{\n    public class Program\n    {\n        public static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Abstractions/BaseAssemblyResolutionTests.cs",
    "content": "﻿using MediatR.DependencyInjectionTests.Contracts.Notifications;\nusing MediatR.DependencyInjectionTests.Contracts.StreamRequests;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Abstractions;\n\npublic abstract class BaseAssemblyResolutionTests(BaseServiceProviderFixture fixture) : IClassFixture<BaseServiceProviderFixture>\n{\n    private readonly IServiceProvider _provider = fixture.Provider;\n\n    [Fact]\n    public void Should_Resolve_Mediator() =>\n        _provider.GetService<IMediator>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Public_RequestHandler() =>\n        _provider.GetService<IRequestHandler<PublicPing, Pong>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Internal_RequestHandler() =>\n        _provider.GetService<IRequestHandler<InternalPing, Pong>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Private_RequestHandler() =>\n        _provider.GetService<IRequestHandler<PrivatePing, Pong>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Public_Void_RequestHandler() =>\n        _provider.GetService<IRequestHandler<PublicVoidPing>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Internal_Void_RequestHandler() =>\n        _provider.GetService<IRequestHandler<InternalVoidPing>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Private_Void_RequestHandler() =>\n        _provider.GetService<IRequestHandler<PrivateVoidPing>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Public_Private_Internal_Notification_Handlers() =>\n        _provider.GetServices<INotificationHandler<Ding>>()\n            .Count()\n            .ShouldBe(3);\n\n    [Fact]\n    public void Should_Resolve_Public_Stream_Request_Handlers() =>\n        _provider.GetService<IStreamRequestHandler<PublicZing, Zong>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Internal_Stream_Request_Handlers() =>\n        _provider.GetService<IStreamRequestHandler<InternalZing, Zong>>()\n            .ShouldNotBeNull();\n\n    [Fact]\n    public void Should_Resolve_Private_Stream_Request_Handlers() =>\n        _provider.GetService<IStreamRequestHandler<PrivateZing, Zong>>()\n            .ShouldNotBeNull();\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Abstractions/BaseServiceProviderFixture.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Abstractions;\n\npublic class BaseServiceProviderFixture\n{\n    public virtual IServiceProvider Provider => throw new NotImplementedException();\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/AutoFacDependencyInjectionTests.cs",
    "content": "﻿using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class AutoFacDependencyInjectionTests : BaseAssemblyResolutionTests\n{\n    public AutoFacDependencyInjectionTests() : base(new AutoFacServiceProviderFixture()) { }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Notifications/Ding.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Notifications;\n\npublic record Ding : INotification\n{\n    public class Door1 : INotificationHandler<Ding>\n    {\n        public Task Handle(Ding notification, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n\n    internal class Door2 : INotificationHandler<Ding>\n    {\n        public Task Handle(Ding notification, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n\n    private class Door3 : INotificationHandler<Ding>\n    {\n        public Task Handle(Ding notification, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/InternalPing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\ninternal record InternalPing : IRequest<Pong>\n{\n    internal class Handler : IRequestHandler<InternalPing, Pong>\n    {\n        public Task<Pong> Handle(InternalPing request, CancellationToken cancellationToken) =>\n            Task.FromResult(new Pong());\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/InternalVoidPing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\ninternal record InternalVoidPing : IRequest\n{\n    internal class Handler : IRequestHandler<InternalVoidPing>\n    {\n        public Task Handle(InternalVoidPing request, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/PrivatePing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\npublic record PrivatePing : IRequest<Pong>\n{\n    private class Handler : IRequestHandler<PrivatePing, Pong>\n    {\n        public Task<Pong> Handle(PrivatePing request, CancellationToken cancellationToken) =>\n            Task.FromResult(new Pong());\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/PrivateVoidPing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\npublic record PrivateVoidPing : IRequest\n{\n    private class Handler : IRequestHandler<PrivateVoidPing>\n    {\n        public Task Handle(PrivateVoidPing request, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/PublicPing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\npublic record PublicPing : IRequest<Pong>\n{\n    public class Handler : IRequestHandler<PublicPing, Pong>\n    {\n        public Task<Pong> Handle(PublicPing request, CancellationToken cancellationToken) =>\n            Task.FromResult(new Pong());\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Requests/PublicVoidPing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Requests;\n\npublic record PublicVoidPing : IRequest\n{\n    public class Handler : IRequestHandler<PublicVoidPing>\n    {\n        public Task Handle(PublicVoidPing request, CancellationToken cancellationToken) =>\n            Task.CompletedTask;\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/Responses/Pong.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.Responses;\n\npublic record Pong;\npublic record Zong;\n"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/StreamRequests/InternalZing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.StreamRequests;\n\ninternal record InternalZing : IStreamRequest<Zong>\n{\n    internal class Handler : IStreamRequestHandler<InternalZing, Zong>\n    {\n        public IAsyncEnumerable<Zong> Handle(InternalZing request, CancellationToken token) =>\n            throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/StreamRequests/PrivateZing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.StreamRequests;\n\ninternal record PrivateZing : IStreamRequest<Zong>\n{\n    private class Handler : IStreamRequestHandler<PrivateZing, Zong>\n    {\n        public IAsyncEnumerable<Zong> Handle(PrivateZing request, CancellationToken token) =>\n            throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Contracts/StreamRequests/PublicZing.cs",
    "content": "﻿namespace MediatR.DependencyInjectionTests.Contracts.StreamRequests;\n\npublic record PublicZing : IStreamRequest<Zong>\n{\n    public class Handler : IStreamRequestHandler<PublicZing, Zong>\n    {\n        public IAsyncEnumerable<Zong> Handle(PublicZing request, CancellationToken token) =>\n            throw new NotImplementedException();\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/DryIocDependencyInjectionTests.cs",
    "content": "﻿using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class DryIocDependencyInjectionTests() \n    : BaseAssemblyResolutionTests(new DryIocServiceProviderFixture());"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/LamarDependencyInjectionTests.cs",
    "content": "using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class LamarDependencyInjectionTests() \n    : BaseAssemblyResolutionTests(new LamarServiceProviderFixture());"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/LightInjectDependencyInjectionTests.cs",
    "content": "using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class LightInjectDependencyInjectionTests() \n    : BaseAssemblyResolutionTests(new LightInjectServiceProviderFixture());"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/MediatR.DependencyInjectionTests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFramework>net10.0</TargetFramework>\n        <ImplicitUsings>enable</ImplicitUsings>\n        <Nullable>enable</Nullable>\n\n        <IsPackable>false</IsPackable>\n        <IsTestProject>true</IsTestProject>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MediatR\\MediatR.csproj\" />\n    </ItemGroup>\n\n\n    <ItemGroup>\n        <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.8.0\"/>\n        <PackageReference Include=\"Shouldly\" Version=\"4.2.1\"/>\n        <PackageReference Include=\"xunit\" Version=\"2.5.3\"/>\n        <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.5.3\"/>\n        <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\"/>\n        <PackageReference Include=\"Microsoft.Extensions.DependencyInjection.Abstractions\" Version=\"10.0.0\"/>\n        <PackageReference Include=\"Microsoft.Extensions.Diagnostics.Testing\" Version=\"10.0.0\"/>\n        <PackageReference Include=\"DryIoc.Microsoft.DependencyInjection\" Version=\"6.2.0\"/>\n        <PackageReference Include=\"Autofac.Extensions.DependencyInjection\" Version=\"8.0.0\"/>\n        <PackageReference Include=\"LightInject.Microsoft.DependencyInjection\" Version=\"4.0.3\" />\n        <PackageReference Include=\"Stashbox.Extensions.DependencyInjection\" Version=\"5.7.0\" />\n        <PackageReference Include=\"Lamar.Microsoft.DependencyInjection\" Version=\"15.0.1\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <Using Include=\"Xunit\" />\n    </ItemGroup>\n\n</Project>"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/MicrosoftDependencyInjectionTests.cs",
    "content": "﻿using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class MicrosoftDependencyInjectionTests : BaseAssemblyResolutionTests\n{\n    public MicrosoftDependencyInjectionTests() : base(new MicrosoftServiceProviderFixture()) { }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/AutoFacServiceProviderFixture.cs",
    "content": "﻿using Autofac;\nusing Autofac.Extensions.DependencyInjection;\nusing MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class AutoFacServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider\n    {\n        get\n        {\n            var services = new ServiceCollection();\n            services.AddFakeLogging();\n            services.AddMediatR(x => x.RegisterServicesFromAssemblyContaining(typeof(Pong)));\n\n            var builder = new ContainerBuilder();\n            builder.Populate(services);\n\n            var container = builder.Build();\n            return new AutofacServiceProvider(container);\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/DryIocServiceProviderFixture.cs",
    "content": "﻿using DryIoc;\nusing DryIoc.Microsoft.DependencyInjection;\nusing MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class DryIocServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider\n    {\n        get\n        {\n            var services = new ServiceCollection();\n            services.AddFakeLogging();\n            services.AddMediatR(x => x.RegisterServicesFromAssemblyContaining(typeof(Pong)));\n\n            var container = new Container(Rules.MicrosoftDependencyInjectionRules);\n            container.WithDependencyInjectionAdapter(services);\n            return container.BuildServiceProvider();\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/LamarServiceProviderFixture.cs",
    "content": "using Lamar;\nusing MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class LamarServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider\n    {\n        get\n        {\n            var services = new ServiceCollection();\n            services.AddFakeLogging();\n            services.AddMediatR(x => x.RegisterServicesFromAssemblyContaining(typeof(Pong)));\n            var c = new Container(services);\n            return c.ServiceProvider;\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/LightInjectServiceProviderFixture.cs",
    "content": "using LightInject;\nusing LightInject.Microsoft.DependencyInjection;\nusing MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class LightInjectServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider\n    {\n        get\n        {\n            var services = new ServiceCollection();\n            services.AddFakeLogging();\n            services.AddMediatR(x => x.RegisterServicesFromAssemblyContaining(typeof(Pong)));\n\n            var container = new ServiceContainer(new ContainerOptions()\n            {\n                EnableMicrosoftCompatibility = true\n            });\n            return container.CreateServiceProvider(services);\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/MicrosoftServiceProviderFixture.cs",
    "content": "﻿using MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class MicrosoftServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider => new ServiceCollection()\n        .AddFakeLogging()\n        .AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(PublicPing).Assembly))\n        .BuildServiceProvider();\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Providers/StashBoxServiceProviderFixture.cs",
    "content": "using MediatR.DependencyInjectionTests.Abstractions;\nusing Microsoft.Extensions.DependencyInjection;\nusing Stashbox;\n\nnamespace MediatR.DependencyInjectionTests.Providers;\n\npublic class StashBoxServiceProviderFixture : BaseServiceProviderFixture\n{\n    public override IServiceProvider Provider\n    {\n        get\n        {\n            var services = new ServiceCollection();\n            services.AddFakeLogging();\n            services.AddMediatR(x => x.RegisterServicesFromAssemblyContaining(typeof(Pong)));\n\n            var container = new StashboxContainer();\n            services.UseStashbox(container);\n            container.Validate();\n\n            return services.BuildServiceProvider();\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/StashBoxDependencyInjectionTests.cs",
    "content": "using MediatR.DependencyInjectionTests.Abstractions;\nusing MediatR.DependencyInjectionTests.Providers;\n\nnamespace MediatR.DependencyInjectionTests;\n\npublic class StashBoxDependencyInjectionTests : BaseAssemblyResolutionTests\n{\n    public StashBoxDependencyInjectionTests() : base(new StashBoxServiceProviderFixture()) { }\n}"
  },
  {
    "path": "test/MediatR.DependencyInjectionTests/Usings.cs",
    "content": "﻿global using MediatR.DependencyInjectionTests.Contracts.Requests;\nglobal using MediatR.DependencyInjectionTests.Contracts.Responses;\nglobal using Shouldly;"
  },
  {
    "path": "test/MediatR.Tests/CreateStreamTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class CreateStreamTests\n{\n\n    public class Ping : IStreamRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingStreamHandler : IStreamRequestHandler<Ping, Pong>\n    {\n        public async IAsyncEnumerable<Pong> Handle(Ping request, [EnumeratorCancellation]CancellationToken cancellationToken)\n        {\n            yield return await Task.Run(() => new Pong { Message = request.Message + \" Pang\" });\n        }\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<CreateStreamTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = mediator.CreateStream(new Ping { Message = \"Ping\" });\n        int i = 0;\n        await foreach (Pong result in response)\n        {\n            if (i == 0)\n            {\n                result.Message.ShouldBe(\"Ping Pang\");\n            }\n\n            i++;\n        }\n\n        i.ShouldBe(1);\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler_via_dynamic_dispatch()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<CreateStreamTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object request = new Ping { Message = \"Ping\" };\n        var response = mediator.CreateStream(request);\n        int i = 0;\n        await foreach (Pong? result in response)\n        {\n            if (i == 0)\n            {\n                result!.Message.ShouldBe(\"Ping Pang\");\n            }\n\n            i++;\n        }\n\n        i.ShouldBe(1);\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler_by_specific_interface()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<CreateStreamTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<ISender, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<ISender>();\n        var response = mediator.CreateStream(new Ping { Message = \"Ping\" });\n        int i = 0;\n        await foreach (Pong result in response)\n        {\n            if (i == 0)\n            {\n                result.Message.ShouldBe(\"Ping Pang\");\n            }\n\n            i++;\n        }\n\n        i.ShouldBe(1);\n    }\n\n    [Fact]\n    public void Should_raise_execption_on_null_request()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        Should.Throw<ArgumentNullException>(() => mediator.CreateStream((Ping) null!));\n    }\n\n    [Fact]\n    public void Should_raise_execption_on_null_request_via_dynamic_dispatch()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        Should.Throw<ArgumentNullException>(() => mediator.CreateStream((object) null!));\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/ExceptionTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class ExceptionTests\n{\n    private readonly IMediator _mediator;\n\n    public class Ping : IRequest<Pong>\n    {\n    }\n\n    public class Pong\n    {\n    }\n\n    public class VoidPing : IRequest\n    {\n    }\n\n    public class Pinged : INotification\n    {\n    }\n\n    public class AsyncPing : IRequest<Pong>\n    {\n    }\n\n    public class AsyncVoidPing : IRequest\n    {\n    }\n\n    public class AsyncPinged : INotification\n    {\n    }\n\n    public class NullPing : IRequest<Pong>\n    {\n    }\n\n    public class VoidNullPing : IRequest\n    {\n    }\n\n    public class NullPinged : INotification\n    {\n    }\n\n    public class NullPingHandler : IRequestHandler<NullPing, Pong>\n    {\n        public Task<Pong> Handle(NullPing request, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(new Pong());\n        }\n    }\n\n    public class VoidNullPingHandler : IRequestHandler<VoidNullPing>\n    {\n        public Task Handle(VoidNullPing request, CancellationToken cancellationToken)\n        {\n            return Task.CompletedTask;\n        }\n    }\n\n    public ExceptionTests()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        _mediator = container.GetRequiredService<IMediator>();\n    }\n\n    [Fact]\n    public async Task Should_throw_for_send()\n    {\n        await Should.ThrowAsync<InvalidOperationException>(async () => await _mediator.Send(new Ping()));\n    }\n\n    [Fact]\n    public async Task Should_throw_for_void_send()\n    {\n        await Should.ThrowAsync<InvalidOperationException>(async () => await _mediator.Send(new VoidPing()));\n    }\n\n    [Fact]\n    public async Task Should_not_throw_for_publish()\n    {\n        Exception ex = null!;\n        try\n        {\n            await _mediator.Publish(new Pinged());\n        }\n        catch (Exception e)\n        {\n            ex = e;\n        }\n        ex.ShouldBeNull();\n    }\n\n    [Fact]\n    public async Task Should_throw_for_async_send()\n    {\n        await Should.ThrowAsync<InvalidOperationException>(async () => await _mediator.Send(new AsyncPing()));\n    }\n\n    [Fact]\n    public async Task Should_throw_for_async_void_send()\n    {\n        await Should.ThrowAsync<InvalidOperationException>(async () => await _mediator.Send(new AsyncVoidPing()));\n    }\n\n    [Fact]\n    public async Task Should_not_throw_for_async_publish()\n    {\n        Exception ex = null!;\n        try\n        {\n            await _mediator.Publish(new AsyncPinged());\n        }\n        catch (Exception e)\n        {\n            ex = e;\n        }\n        ex.ShouldBeNull();\n    }\n\n    [Fact]\n    public async Task Should_throw_argument_exception_for_send_when_request_is_null()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPing>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        NullPing request = null!;\n\n        await Should.ThrowAsync<ArgumentNullException>(async () => await mediator.Send(request));\n    }\n\n    [Fact]\n    public async Task Should_throw_argument_exception_for_void_send_when_request_is_null()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<VoidNullPing>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        VoidNullPing request = null!;\n\n        await Should.ThrowAsync<ArgumentNullException>(async () => await mediator.Send(request));\n    }\n\n    [Fact]\n    public async Task Should_throw_argument_exception_for_publish_when_request_is_null()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        NullPinged notification = null!;\n\n        await Should.ThrowAsync<ArgumentNullException>(async () => await mediator.Publish(notification));\n    }\n\n    [Fact]\n    public async Task Should_throw_argument_exception_for_publish_when_request_is_null_object()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object notification = null!;\n\n        await Should.ThrowAsync<ArgumentNullException>(async () => await mediator.Publish(notification));\n    }\n\n    [Fact]\n    public async Task Should_throw_argument_exception_for_publish_when_request_is_not_notification()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object notification = \"totally not notification\";\n\n        await Should.ThrowAsync<ArgumentException>(async () => await mediator.Publish(notification));\n    }\n\n    public class PingException : IRequest\n    {\n\n    }\n\n    public class PingExceptionHandler : IRequestHandler<PingException>\n    {\n        public Task Handle(PingException request, CancellationToken cancellationToken)\n        {\n            throw new NotImplementedException();\n        }\n    }\n\n    [Fact]\n    public async Task Should_throw_exception_for_non_generic_send_when_exception_occurs()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object pingException = new PingException();\n\n        await Should.ThrowAsync<NotImplementedException>(async () => await mediator.Send(pingException));\n    }\n\n    [Fact]\n    public async Task Should_throw_exception_for_non_request_send()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object nonRequest = new NonRequest();\n\n        var argumentException = await Should.ThrowAsync<ArgumentException>(async () => await mediator.Send(nonRequest));\n        Assert.StartsWith(\"NonRequest does not implement IRequest\", argumentException.Message);\n    }\n\n    public class NonRequest\n    {\n\n    }\n\n    [Fact]\n    public async Task Should_throw_exception_for_generic_send_when_exception_occurs()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<NullPinged>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n        var mediator = container.GetRequiredService<IMediator>();\n\n        PingException pingException = new PingException();\n\n        await Should.ThrowAsync<NotImplementedException>(async () => await mediator.Send(pingException));\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/GenericRequestHandlerTests.cs",
    "content": "﻿using System.Linq;\r\nusing MediatR.Tests.MicrosoftExtensionsDI;\r\n\r\nnamespace MediatR.Tests\r\n{\r\n    [Collection(nameof(ServiceFactoryCollectionBehavior))]\r\n    public class GenericRequestHandlerTests : BaseGenericRequestHandlerTests\r\n    {\r\n\r\n        [Theory]\r\n        [InlineData(9, 3, 3)]\r\n        [InlineData(10, 4, 4)]\r\n        [InlineData(1, 1, 1)]\r\n        [InlineData(50, 3, 3)]\r\n        public void ShouldResolveAllCombinationsOfGenericHandler(int numberOfClasses, int numberOfInterfaces, int numberOfTypeParameters)\r\n        {\r\n            var services = new ServiceCollection();\r\n\r\n            var dynamicAssembly = GenerateCombinationsTestAssembly(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);\r\n\r\n            services.AddMediatR(cfg =>\r\n            {\r\n                cfg.RegisterServicesFromAssemblies(dynamicAssembly);\r\n                cfg.RegisterGenericHandlers = true;\r\n            });\r\n\r\n            var provider = services.BuildServiceProvider();\r\n\r\n            var dynamicRequestType = dynamicAssembly.GetType(\"DynamicRequest\")!;\r\n\r\n            int expectedCombinations = CalculateTotalCombinations(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);\r\n\r\n            var testClasses = Enumerable.Range(1, numberOfClasses)\r\n                .Select(i => dynamicAssembly.GetType($\"TestClass{i}\")!)\r\n                .ToArray();\r\n\r\n            var combinations = GenerateCombinations(testClasses, numberOfInterfaces);          \r\n\r\n            foreach (var combination in combinations)\r\n            {\r\n                var concreteRequestType = dynamicRequestType.MakeGenericType(combination);\r\n                var requestHandlerInterface = typeof(IRequestHandler<>).MakeGenericType(concreteRequestType);\r\n\r\n                var handler = provider.GetService(requestHandlerInterface);\r\n                handler.ShouldNotBeNull($\"Handler for {concreteRequestType} should not be null\");\r\n            }            \r\n        }\r\n\r\n        [Theory]\r\n        [InlineData(9, 3, 3)]\r\n        [InlineData(10, 4, 4)]\r\n        [InlineData(1, 1, 1)]\r\n        [InlineData(50, 3, 3)]\r\n        public void ShouldRegisterTheCorrectAmountOfHandlers(int numberOfClasses, int numberOfInterfaces, int numberOfTypeParameters)\r\n        {  \r\n            var dynamicAssembly = GenerateCombinationsTestAssembly(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);          \r\n            int expectedCombinations = CalculateTotalCombinations(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);\r\n            var testClasses = Enumerable.Range(1, numberOfClasses)\r\n               .Select(i => dynamicAssembly.GetType($\"TestClass{i}\")!)\r\n               .ToArray();\r\n            var combinations = GenerateCombinations(testClasses, numberOfInterfaces);\r\n            combinations.Count.ShouldBe(expectedCombinations, $\"Should have tested all {expectedCombinations} combinations\");\r\n        }\r\n\r\n        [Theory]\r\n        [InlineData(9, 3, 3)]\r\n        [InlineData(10, 4, 4)]\r\n        [InlineData(1, 1, 1)]\r\n        [InlineData(50, 3, 3)]\r\n        public void ShouldNotRegisterDuplicateHandlers(int numberOfClasses, int numberOfInterfaces, int numberOfTypeParameters)\r\n        {\r\n            var dynamicAssembly = GenerateCombinationsTestAssembly(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);\r\n            int expectedCombinations = CalculateTotalCombinations(numberOfClasses, numberOfInterfaces, numberOfTypeParameters);\r\n            var testClasses = Enumerable.Range(1, numberOfClasses)\r\n               .Select(i => dynamicAssembly.GetType($\"TestClass{i}\")!)\r\n               .ToArray();\r\n            var combinations = GenerateCombinations(testClasses, numberOfInterfaces);\r\n            var hasDuplicates = combinations\r\n              .Select(x => string.Join(\", \", x.Select(y => y.Name)))\r\n              .GroupBy(x => x)\r\n              .Any(g => g.Count() > 1);\r\n\r\n            hasDuplicates.ShouldBeFalse();\r\n        }\r\n\r\n        [Fact]\r\n        public void ShouldThrowExceptionWhenTypesClosingExceedsMaximum()\r\n        {\r\n            IServiceCollection services = new ServiceCollection();\r\n            services.AddFakeLogging();\r\n\r\n            var assembly = GenerateTypesClosingExceedsMaximumAssembly();\r\n\r\n            Should.Throw<ArgumentException>(() =>\r\n            {\r\n                services.AddMediatR(cfg =>\r\n                {\r\n                    cfg.RegisterServicesFromAssembly(assembly);\r\n                    cfg.RegisterGenericHandlers = true;\r\n                });\r\n            })\r\n            .Message.ShouldContain(\"One of the generic type parameter's count of types that can close exceeds the maximum length allowed\");\r\n        }\r\n\r\n        [Fact]\r\n        public void ShouldThrowExceptionWhenGenericHandlerRegistrationsExceedsMaximum()\r\n        {\r\n            IServiceCollection services = new ServiceCollection();\r\n            services.AddFakeLogging();\r\n\r\n            var assembly = GenerateHandlerRegistrationsExceedsMaximumAssembly();\r\n\r\n            Should.Throw<ArgumentException>(() =>\r\n            {\r\n                services.AddMediatR(cfg =>\r\n                {\r\n                    cfg.RegisterServicesFromAssembly(assembly);\r\n                    cfg.RegisterGenericHandlers = true;\r\n                });\r\n            })\r\n            .Message.ShouldContain(\"The total number of generic type registrations exceeds the maximum allowed\");\r\n        }\r\n\r\n        [Fact]\r\n        public void ShouldThrowExceptionWhenGenericTypeParametersExceedsMaximum()\r\n        {\r\n            IServiceCollection services = new ServiceCollection();\r\n            services.AddFakeLogging();\r\n\r\n            var assembly = GenerateGenericTypeParametersExceedsMaximumAssembly();\r\n\r\n            Should.Throw<ArgumentException>(() =>\r\n            {\r\n                services.AddMediatR(cfg =>\r\n                {\r\n                    cfg.RegisterServicesFromAssembly(assembly);\r\n                    cfg.RegisterGenericHandlers = true;\r\n                });\r\n            })\r\n            .Message.ShouldContain(\"The number of generic type parameters exceeds the maximum allowed\");\r\n        }\r\n\r\n        [Fact]\r\n        public void ShouldThrowExceptionWhenTimeoutOccurs()\r\n        {\r\n            IServiceCollection services = new ServiceCollection();\r\n            services.AddFakeLogging();\r\n\r\n            var assembly = GenerateTimeoutOccursAssembly();\r\n\r\n            Should.Throw<TimeoutException>(() =>\r\n            {\r\n                services.AddMediatR(cfg =>\r\n                {\r\n                    cfg.MaxGenericTypeParameters = 0;\r\n                    cfg.MaxGenericTypeRegistrations = 0;\r\n                    cfg.MaxTypesClosing = 0;\r\n                    cfg.RegistrationTimeout = 100;\r\n                    cfg.RegisterGenericHandlers = true;\r\n                    cfg.RegisterServicesFromAssembly(assembly);\r\n                });\r\n            })\r\n            .Message.ShouldBe(\"The generic handler registration process timed out.\");\r\n        }\r\n\r\n        [Fact]\r\n        public void ShouldNotRegisterGenericHandlersWhenOptingOut()\r\n        {\r\n            IServiceCollection services = new ServiceCollection();\r\n            services.AddFakeLogging();\r\n\r\n            var assembly = GenerateOptOutAssembly();\r\n            services.AddMediatR(cfg =>\r\n            {\r\n                //opt out flag set\r\n                cfg.RegisterGenericHandlers = false;\r\n                cfg.RegisterServicesFromAssembly(assembly);\r\n            });\r\n\r\n            var provider = services.BuildServiceProvider();\r\n            var testClasses = Enumerable.Range(1, 2)\r\n                .Select(i => assembly.GetType($\"TestClass{i}\")!)\r\n                .ToArray();\r\n            var requestType = assembly.GetType(\"OptOutRequest\")!;\r\n            var combinations = GenerateCombinations(testClasses, 2);\r\n\r\n            var concreteRequestType = requestType.MakeGenericType(combinations.First());\r\n            var requestHandlerInterface = typeof(IRequestHandler<>).MakeGenericType(concreteRequestType);\r\n\r\n            var handler = provider.GetService(requestHandlerInterface);\r\n            handler.ShouldBeNull($\"Handler for {concreteRequestType} should be null\");\r\n\r\n\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "test/MediatR.Tests/GenericTypeConstraintsTests.cs",
    "content": "using System.Reflection;\nusing System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System;\nusing System.Linq;\nusing Shouldly;\nusing System.Threading.Tasks;\nusing Xunit;\n\npublic class GenericTypeConstraintsTests\n{\n    public interface IGenericTypeRequestHandlerTestClass<TRequest> where TRequest : IBaseRequest\n    {\n        Type[] Handle(TRequest request);\n    }\n\n    public abstract class GenericTypeRequestHandlerTestClass<TRequest> : IGenericTypeRequestHandlerTestClass<TRequest>\n        where TRequest : IBaseRequest\n    {\n        public bool IsIRequest { get; }\n\n\n        public bool IsIRequestT { get; }\n\n        public bool IsIBaseRequest { get; }\n\n        public GenericTypeRequestHandlerTestClass()\n        {\n            IsIRequest = typeof(IRequest).IsAssignableFrom(typeof(TRequest));\n            IsIRequestT = typeof(TRequest).GetInterfaces()\n                .Any(x => x.GetTypeInfo().IsGenericType &&\n                          x.GetGenericTypeDefinition() == typeof(IRequest<>));\n\n            IsIBaseRequest = typeof(IBaseRequest).IsAssignableFrom(typeof(TRequest));\n        }\n\n        public Type[] Handle(TRequest request)\n        {\n            return typeof(TRequest).GetInterfaces();\n        }\n    }\n\n    public class GenericTypeConstraintPing : GenericTypeRequestHandlerTestClass<Ping>\n    {\n\n    }\n\n    public class GenericTypeConstraintJing : GenericTypeRequestHandlerTestClass<Jing>\n    {\n\n    }\n\n    public class Jing : IRequest\n    {\n        public string? Message { get; set; }\n    }\n\n    public class JingHandler : IRequestHandler<Jing>\n    {\n        public Task Handle(Jing request, CancellationToken cancellationToken)\n        {\n            // empty handle\n            return Task.CompletedTask;\n        }\n    }\n\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\n        }\n    }\n\n    private readonly IMediator _mediator;\n\n    public GenericTypeConstraintsTests()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<GenericTypeConstraintsTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        _mediator = container.GetRequiredService<IMediator>();\n    }\n\n    [Fact]\n    public async Task Should_Resolve_Void_Return_Request()\n    {\n        // Create Request\n        var jing = new Jing { Message = \"Jing\" };\n\n        // Test mediator still works sending request\n        await _mediator.Send(jing);\n\n        // Create new instance of type constrained class\n        var genericTypeConstraintsVoidReturn = new  GenericTypeConstraintJing();\n\n        // Assert it is of type IRequest and IRequest<T>\n        Assert.True(genericTypeConstraintsVoidReturn.IsIRequest);\n        Assert.False(genericTypeConstraintsVoidReturn.IsIRequestT);\n        Assert.True(genericTypeConstraintsVoidReturn.IsIBaseRequest);\n\n        // Verify it is of IRequest and IBaseRequest\n        var results = genericTypeConstraintsVoidReturn.Handle(jing);\n\n        Assert.Equal(2, results.Length);\n\n        results.ShouldNotContain(typeof(IRequest<Unit>));\n        results.ShouldContain(typeof(IBaseRequest));\n        results.ShouldContain(typeof(IRequest));\n    }\n\n    [Fact]\n    public async Task Should_Resolve_Response_Return_Request()\n    {\n        // Create Request\n        var ping = new Ping { Message = \"Ping\" };\n\n        // Test mediator still works sending request and gets response\n        var pingResponse = await _mediator.Send(ping);\n        pingResponse.Message.ShouldBe(\"Ping Pong\");\n\n        // Create new instance of type constrained class\n        var genericTypeConstraintsResponseReturn = new GenericTypeConstraintPing();\n\n        // Assert it is of type IRequest<T> but not IRequest\n        Assert.False(genericTypeConstraintsResponseReturn.IsIRequest);\n        Assert.True(genericTypeConstraintsResponseReturn.IsIRequestT);\n        Assert.True(genericTypeConstraintsResponseReturn.IsIBaseRequest);\n\n        // Verify it is of IRequest<Pong> and IBaseRequest, but not IRequest\n        var results = genericTypeConstraintsResponseReturn.Handle(ping);\n\n        Assert.Equal(2, results.Length);\n\n        results.ShouldContain(typeof(IRequest<Pong>));\n        results.ShouldContain(typeof(IBaseRequest));\n        results.ShouldNotContain(typeof(IRequest));\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/GlobalUsings.cs",
    "content": "global using Microsoft.Extensions.DependencyInjection;\nglobal using Shouldly;\nglobal using System;\nglobal using System.Threading;\nglobal using System.Threading.Tasks;\nglobal using Xunit;\n"
  },
  {
    "path": "test/MediatR.Tests/Licensing/LicenseValidatorTests.cs",
    "content": "using System;\nusing System.Security.Claims;\nusing MediatR.Licensing;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Testing;\nusing Shouldly;\nusing Xunit;\nusing License = MediatR.Licensing.License;\n\nnamespace MediatR.Tests.Licensing;\n\npublic class LicenseValidatorTests\n{\n    [Fact]\n    public void Should_return_invalid_when_no_claims()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = new License();\n        \n        license.IsConfigured.ShouldBeFalse();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages\n            .ShouldContain(log => log.Level == LogLevel.Warning);\n    }   \n    \n        \n    [Fact]\n    public void Should_return_valid_when_community()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()), \n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Community)),\n            new Claim(\"type\", nameof(ProductType.Bundle)));\n        \n        license.IsConfigured.ShouldBeTrue();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages.ShouldNotContain(log => log.Level == LogLevel.Error \n                                            || log.Level == LogLevel.Warning\n                                            || log.Level == LogLevel.Critical);\n    }\n    \n    [Fact]\n    public void Should_return_invalid_when_not_correct_type()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()), \n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddYears(1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Professional)),\n            new Claim(\"type\", nameof(ProductType.AutoMapper)));\n        \n        license.IsConfigured.ShouldBeTrue();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages\n            .ShouldContain(log => log.Level == LogLevel.Error);\n    }\n    \n    [Fact]\n    public void Should_return_invalid_when_expired()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddYears(-1).ToUnixTimeSeconds().ToString()), \n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Professional)),\n            new Claim(\"type\", nameof(ProductType.MediatR)));\n        \n        license.IsConfigured.ShouldBeTrue();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages\n            .ShouldContain(log => log.Level == LogLevel.Error);\n    }\n    \n    [Fact]\n    public void Should_allow_perpetual_license_when_build_date_before_expiration()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var buildDate = DateTimeOffset.UtcNow.AddDays(-30);\n        var licenseValidator = new LicenseValidator(factory, buildDate);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddYears(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Professional)),\n            new Claim(\"type\", nameof(ProductType.MediatR)),\n            new Claim(\"perpetual\", \"true\"));\n\n        license.IsConfigured.ShouldBeTrue();\n        license.IsPerpetual.ShouldBeTrue();\n\n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n        logMessages.ShouldNotContain(log => log.Level == LogLevel.Error);\n        logMessages.ShouldContain(log => log.Level == LogLevel.Information &&\n                                         log.Message.Contains(\"perpetual\"));\n    }\n\n    [Fact]\n    public void Should_reject_perpetual_license_when_build_date_after_expiration()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var buildDate = DateTimeOffset.UtcNow.AddDays(-5); // Build date in past, after expiration\n        var licenseValidator = new LicenseValidator(factory, buildDate);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddYears(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(-10).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Professional)),\n            new Claim(\"type\", nameof(ProductType.MediatR)),\n            new Claim(\"perpetual\", \"true\"));\n\n        license.IsConfigured.ShouldBeTrue();\n        license.IsPerpetual.ShouldBeTrue();\n\n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n        logMessages.ShouldContain(log => log.Level == LogLevel.Error &&\n                                        log.Message.Contains(\"expired\"));\n    }\n\n    [Fact]\n    public void Should_handle_missing_perpetual_claim()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Community)),\n            new Claim(\"type\", nameof(ProductType.Bundle)));\n\n        license.IsConfigured.ShouldBeTrue();\n        license.IsPerpetual.ShouldBeFalse();\n\n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n        logMessages.ShouldNotContain(log => log.Level == LogLevel.Error\n                                            || log.Level == LogLevel.Warning\n                                            || log.Level == LogLevel.Critical);\n    }\n\n    [Fact]\n    public void Should_fall_back_to_expiration_error_when_perpetual_and_build_date_is_null()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var licenseValidator = new LicenseValidator(factory, (DateTimeOffset?)null);\n        var license = new License(\n            new Claim(\"account_id\", Guid.NewGuid().ToString()),\n            new Claim(\"customer_id\", Guid.NewGuid().ToString()),\n            new Claim(\"sub_id\", Guid.NewGuid().ToString()),\n            new Claim(\"iat\", DateTimeOffset.UtcNow.AddDays(-10).ToUnixTimeSeconds().ToString()),\n            new Claim(\"exp\", DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds().ToString()),\n            new Claim(\"edition\", nameof(Edition.Community)),\n            new Claim(\"type\", nameof(ProductType.Bundle)),\n            new Claim(\"perpetual\", \"true\"));\n\n        license.IsConfigured.ShouldBeTrue();\n        license.IsPerpetual.ShouldBeTrue();\n\n        // Validator was created with null buildDate - perpetual licensing cannot be applied.\n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n        logMessages.ShouldContain(log => log.Level == LogLevel.Warning && log.Message.Contains(\"perpetual\"));\n        logMessages.ShouldContain(log => log.Level == LogLevel.Error);\n    }\n    \n    [Fact(Skip = \"Needs license\")]\n    public void Should_return_valid_for_actual_valid_license()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        var config = new MediatRServiceConfiguration\n        {\n            LicenseKey =\n                \"<>\"\n        };\n        var licenseAccessor = new LicenseAccessor(config, factory);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = licenseAccessor.Current;\n        \n        license.IsConfigured.ShouldBeTrue();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages\n            .ShouldNotContain(log => log.Level == LogLevel.Error);\n    }\n    \n    [Fact(Skip = \"Needs license\")]\n    public void Should_return_valid_for_actual_valid_license_via_static_property()\n    {\n        var factory = new LoggerFactory();\n        var provider = new FakeLoggerProvider();\n        factory.AddProvider(provider);\n\n        Mediator.LicenseKey = \"<>\";\n        var licenseAccessor = new LicenseAccessor(factory);\n\n        var licenseValidator = new LicenseValidator(factory);\n        var license = licenseAccessor.Current;\n        \n        license.IsConfigured.ShouldBeTrue();\n        \n        licenseValidator.Validate(license);\n\n        var logMessages = provider.Collector.GetSnapshot();\n     \n        logMessages\n            .ShouldNotContain(log => log.Level == LogLevel.Error);\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MediatR.Tests.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFrameworks>net10.0</TargetFrameworks>\n    <Nullable>enable</Nullable>\n    <NoWarn>$(NoWarn);CS8002;</NoWarn>\n    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>\n    <SignAssembly>true</SignAssembly>\n    <AssemblyOriginatorKeyFile>..\\..\\MediatR.snk</AssemblyOriginatorKeyFile>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\" '$(IsWindows)' == 'true' \">\n    <TargetFrameworks>$(TargetFrameworks);net462</TargetFrameworks>\n  </PropertyGroup>\n  \n  <ItemGroup>\n    <ProjectReference Include=\"..\\..\\src\\MediatR\\MediatR.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"IsExternalInit\" Version=\"1.0.3\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Scrutor\" Version=\"6.1.0\" />\n    <PackageReference Include=\"xunit\" Version=\"2.6.1\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.8.0\" />\n    <PackageReference Include=\"Shouldly\" Version=\"4.2.1\" />\n    <PackageReference Include=\"System.Reflection.TypeExtensions\" Version=\"4.7.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"10.0.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection.Abstractions\" Version=\"10.0.0\" />\n    <PackageReference Include=\"Microsoft.Extensions.Diagnostics.Testing\" Version=\"10.0.0\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.5.3\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/AssemblyResolutionTests.cs",
    "content": "﻿using Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing Shouldly;\nusing Xunit;\n\npublic class AssemblyResolutionTests\n{\n    private readonly IServiceProvider _provider;\n\n    public AssemblyResolutionTests()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.RegisterGenericHandlers = true;\n        });\n        _provider = services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public void ShouldResolveMediator()\n    {\n        _provider.GetService<IMediator>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<Ping, Pong>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveInternalHandler()\n    {\n        _provider.GetService<IRequestHandler<InternalPing>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveNotificationHandlers()\n    {\n        _provider.GetServices<INotificationHandler<Pinged>>().Count().ShouldBe(4);\n    }\n\n    [Fact]\n    public void ShouldResolveStreamHandlers()\n    {\n        _provider.GetService<IStreamRequestHandler<StreamPing, Pong>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldRequireAtLeastOneAssembly()\n    {\n        var services = new ServiceCollection();\n\n        Action registration = () => services.AddMediatR(_ => { });\n\n        registration.ShouldThrow<ArgumentException>();\n    }\n\n    [Fact]\n    public void ShouldResolveGenericVoidRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<OpenGenericVoidRequest<ConcreteTypeArgument>>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveGenericReturnTypeRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<OpenGenericReturnTypeRequest<ConcreteTypeArgument>, string>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveGenericPingRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<GenericPing<Pong>, Pong>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveVoidGenericPingRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<VoidGenericPing<Pong>>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldNotThrowWhenAssemblyThrowsReflectionTypeLoadException()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n\n        Action registration = () => services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly, new BrokenAssembly());\n        });\n\n        registration.ShouldNotThrow();\n\n        var provider = services.BuildServiceProvider();\n        provider.GetService<IRequestHandler<Ping, Pong>>().ShouldNotBeNull();\n    }\n\n    private class BrokenAssembly : Assembly\n    {\n        public override IEnumerable<TypeInfo> DefinedTypes =>\n            throw new ReflectionTypeLoadException(\n                new Type?[] { typeof(string), null, typeof(int) },\n                new Exception?[] { null, new Exception(\"ByRef-like type cannot be loaded\"), null });\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/BaseGenericRequestHandlerTests.cs",
    "content": "﻿using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Reflection.Emit;\r\nusing System.Reflection;\r\nusing System.Threading;\r\nusing System.Threading.Tasks;\r\n\r\nnamespace MediatR.Tests.MicrosoftExtensionsDI\r\n{\r\n    public abstract class BaseGenericRequestHandlerTests\r\n    { \r\n        protected static Assembly GenerateTypesClosingExceedsMaximumAssembly() =>\r\n            CreateAssemblyModuleBuilder(\"ExceedsMaximumTypesClosingAssembly\", 201, 1, CreateHandlerForExceedsMaximumClassesTest);\r\n\r\n        protected static Assembly GenerateHandlerRegistrationsExceedsMaximumAssembly() =>\r\n            CreateAssemblyModuleBuilder(\"ExceedsMaximumHandlerRegistrationsAssembly\", 500, 10, CreateHandlerForExceedsMaximumHandlerRegistrationsTest);\r\n\r\n        protected static Assembly GenerateGenericTypeParametersExceedsMaximumAssembly() =>\r\n            CreateAssemblyModuleBuilder(\"ExceedsMaximumGenericTypeParametersAssembly\", 1, 1, CreateHandlerForExceedsMaximumGenericTypeParametersTest);\r\n\r\n        protected static Assembly GenerateTimeoutOccursAssembly() =>\r\n            CreateAssemblyModuleBuilder(\"TimeOutOccursAssembly\", 400, 3, CreateHandlerForTimeoutOccursTest);\r\n\r\n        protected static Assembly GenerateOptOutAssembly() =>\r\n            CreateAssemblyModuleBuilder(\"OptOutAssembly\", 2, 2, CreateHandlerForOptOutTest);\r\n\r\n        protected static void CreateHandlerForOptOutTest(ModuleBuilder moduleBuilder) =>\r\n            CreateRequestHandler(moduleBuilder, \"OptOutRequest\", 2);\r\n\r\n        protected static void CreateHandlerForMissingConstraintsTest(ModuleBuilder moduleBuilder) =>\r\n          CreateRequestHandler(moduleBuilder, \"MissingConstraintsRequest\", 3, 0, false);\r\n\r\n        protected static void CreateHandlerForExceedsMaximumClassesTest(ModuleBuilder moduleBuilder) =>\r\n            CreateRequestHandler(moduleBuilder, \"ExceedsMaximumTypesClosingRequest\", 1);\r\n\r\n        protected static void CreateHandlerForExceedsMaximumHandlerRegistrationsTest(ModuleBuilder moduleBuilder) =>\r\n            CreateRequestHandler(moduleBuilder, \"ExceedsMaximumHandlerRegistrationsRequest\", 4);\r\n\r\n        protected static void CreateHandlerForExceedsMaximumGenericTypeParametersTest(ModuleBuilder moduleBuilder) =>\r\n            CreateRequestHandler(moduleBuilder, \"ExceedsMaximumGenericTypeParametersRequest\", 11, 1);\r\n\r\n        protected static void CreateHandlerForTimeoutOccursTest(ModuleBuilder moduleBuilder) =>\r\n            CreateRequestHandler(moduleBuilder, \"TimeoutOccursRequest\", 3);\r\n\r\n        protected static void CreateHandlerForCombinationsTest(ModuleBuilder moduleBuilder, int numberOfGenericParameters) =>\r\n            CreateRequestHandler(moduleBuilder, \"DynamicRequest\", numberOfGenericParameters);\r\n\r\n        protected static void CreateClass(ModuleBuilder moduleBuilder, string className, Type interfaceType)\r\n        {\r\n            TypeBuilder typeBuilder = moduleBuilder.DefineType(className, TypeAttributes.Public);\r\n            typeBuilder.AddInterfaceImplementation(interfaceType);\r\n            typeBuilder.CreateTypeInfo();\r\n        }\r\n\r\n        protected static Type CreateInterface(ModuleBuilder moduleBuilder, string interfaceName)\r\n        {\r\n            TypeBuilder interfaceBuilder = moduleBuilder.DefineType(interfaceName, TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract);\r\n            return interfaceBuilder.CreateTypeInfo().AsType();\r\n        }\r\n\r\n        protected static AssemblyBuilder CreateAssemblyModuleBuilder(string name, int classes, int interfaces, Action<ModuleBuilder> handlerCreation)\r\n        {\r\n            AssemblyName assemblyName = new AssemblyName(name);\r\n            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);\r\n            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(\"MainModule\");\r\n\r\n            CreateTestClassesAndInterfaces(moduleBuilder, classes, interfaces);\r\n            handlerCreation.Invoke(moduleBuilder);\r\n\r\n            return assemblyBuilder;\r\n        }\r\n\r\n        protected static AssemblyBuilder GenerateCombinationsTestAssembly(int classes, int interfaces, int genericParameters)\r\n        {\r\n            AssemblyName assemblyName = new AssemblyName(\"DynamicAssembly\");\r\n            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);\r\n            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(\"MainModule\");\r\n\r\n            CreateTestClassesAndInterfaces(moduleBuilder, classes, interfaces);\r\n            CreateHandlerForCombinationsTest(moduleBuilder, genericParameters);\r\n\r\n            return assemblyBuilder;\r\n        }\r\n\r\n        protected static string[] GetGenericParameterNames(int numberOfTypeParameters) => \r\n            Enumerable.Range(1, numberOfTypeParameters).Select(i => $\"T{i}\").ToArray();\r\n\r\n        protected static void CreateRequestHandler(ModuleBuilder moduleBuilder, string requestName, int numberOfTypeParameters, int numberOfInterfaces = 0, bool includeConstraints = true)\r\n        {\r\n            if(numberOfInterfaces == 0)\r\n            {\r\n                numberOfInterfaces = numberOfTypeParameters;\r\n            }\r\n\r\n            // Define the dynamic request class\r\n            var handlerTypeBuilder = moduleBuilder!.DefineType($\"{requestName}Handler\", TypeAttributes.Public);\r\n            var requestTypeBuilder = moduleBuilder!.DefineType(requestName, TypeAttributes.Public);\r\n\r\n            // Define the generic parameters\r\n            string[] genericParameterNames = GetGenericParameterNames(numberOfTypeParameters);\r\n            var handlerGenericParameters = handlerTypeBuilder.DefineGenericParameters(genericParameterNames);\r\n            var requestGenericParameters = requestTypeBuilder.DefineGenericParameters(genericParameterNames);\r\n            requestTypeBuilder.AddInterfaceImplementation(typeof(IRequest));\r\n\r\n            if(includeConstraints) \r\n            {\r\n                for (int i = 0; i < numberOfTypeParameters; i++)\r\n                {\r\n                    int interfaceIndex = i % numberOfInterfaces + 1;\r\n\r\n                    var constraintType = moduleBuilder.Assembly.GetType($\"ITestInterface{interfaceIndex}\");\r\n                    handlerGenericParameters[i].SetInterfaceConstraints(constraintType!);\r\n                    requestGenericParameters[i].SetInterfaceConstraints(constraintType!);\r\n                }\r\n            }\r\n\r\n            var requestType = requestTypeBuilder.CreateTypeInfo().AsType();\r\n            handlerTypeBuilder.AddInterfaceImplementation(typeof(IRequestHandler<>).MakeGenericType(requestType));\r\n\r\n            // Define the Handle method\r\n            MethodBuilder handleMethodBuilder = handlerTypeBuilder.DefineMethod(\r\n                \"Handle\",\r\n                MethodAttributes.Public | MethodAttributes.Virtual,\r\n                typeof(Task),\r\n                new[] { requestType, typeof(CancellationToken) });\r\n\r\n            ILGenerator ilGenerator = handleMethodBuilder.GetILGenerator();\r\n\r\n            ilGenerator.Emit(OpCodes.Ret);\r\n\r\n            // Implement the interface method\r\n            handlerTypeBuilder.DefineMethodOverride(handleMethodBuilder, typeof(IRequestHandler<>).MakeGenericType(requestType).GetMethod(\"Handle\")!);\r\n\r\n            // Create the dynamic request class\r\n            handlerTypeBuilder.CreateTypeInfo();\r\n        }\r\n\r\n        protected static void CreateTestClassesAndInterfaces(ModuleBuilder moduleBuilder, int numberOfClasses, int numberOfInterfaces)\r\n        {\r\n\r\n            Type[] interfaces = new Type[numberOfInterfaces];\r\n            for (int i = 1; i <= numberOfInterfaces; i++)\r\n            {\r\n                string interfaceName = $\"ITestInterface{i}\";\r\n                interfaces[i - 1] = CreateInterface(moduleBuilder, interfaceName);\r\n            }\r\n\r\n            for (int i = 1; i <= numberOfClasses; i++)\r\n            {\r\n                string className = $\"TestClass{i}\";\r\n                Type interfaceType = interfaces[(i - 1) % numberOfInterfaces];\r\n                CreateClass(moduleBuilder, className, interfaceType);\r\n            }\r\n        }\r\n\r\n        protected List<Type[]> GenerateCombinations(Type[] types, int interfaces)\r\n        {\r\n            var groups = new List<Type>[interfaces];\r\n            for (int i = 0; i < interfaces; i++)\r\n            {\r\n                groups[i] = types.Where((t, index) => index % interfaces == i).ToList();\r\n            }\r\n\r\n            return GenerateCombinationsRecursive(groups, 0);\r\n        }\r\n\r\n        protected List<Type[]> GenerateCombinationsRecursive(List<Type>[] groups, int currentGroup)\r\n        {\r\n            var result = new List<Type[]>();\r\n\r\n            if (currentGroup == groups.Length)\r\n            {\r\n                result.Add(Array.Empty<Type>());\r\n                return result;\r\n            }\r\n\r\n            foreach (var type in groups[currentGroup])\r\n            {\r\n                foreach (var subCombination in GenerateCombinationsRecursive(groups, currentGroup + 1))\r\n                {\r\n                    result.Add(new[] { type }.Concat(subCombination).ToArray());\r\n                }\r\n            }\r\n\r\n            return result;\r\n        }\r\n\r\n        protected static int CalculateTotalCombinations(int numberOfClasses, int numberOfInterfaces, int numberOfTypeParameters)\r\n        {\r\n            var testClasses = Enumerable.Range(1, numberOfClasses)\r\n                .Select(i => $\"TestClass{i}\")\r\n                .ToArray();\r\n\r\n            var groups = new List<string>[numberOfInterfaces];\r\n            for (int i = 0; i < numberOfInterfaces; i++)\r\n            {\r\n                groups[i] = testClasses.Where((t, index) => index % numberOfInterfaces == i).ToList();\r\n            }\r\n\r\n            return groups\r\n                .Take(numberOfTypeParameters)\r\n                .Select(group => group.Count)\r\n                .Aggregate(1, (a, b) => a * b);\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/CustomMediatorTests.cs",
    "content": "﻿using Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Linq;\nusing Shouldly;\nusing Xunit;\n\npublic class CustomMediatorTests\n{\n    private readonly IServiceProvider _provider;\n\n    public CustomMediatorTests()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddMediatR(cfg =>\n        {\n            cfg.MediatorImplementationType = typeof(MyCustomMediator);\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n        });\n        _provider = services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public void ShouldResolveMediator()\n    {\n        _provider.GetService<IMediator>().ShouldNotBeNull();\n        _provider.GetRequiredService<IMediator>().GetType().ShouldBe(typeof(MyCustomMediator));\n    }\n\n    [Fact]\n    public void ShouldResolveRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<Ping, Pong>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveNotificationHandlers()\n    {\n        _provider.GetServices<INotificationHandler<Pinged>>().Count().ShouldBe(4);\n    }\n\n    [Fact]\n    public void Can_Call_AddMediatr_multiple_times()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.MediatorImplementationType = typeof(MyCustomMediator);\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n        });\n            \n        // Call AddMediatr again, this should NOT override our custom mediatr (With MS DI, last registration wins)\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests)));\n\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetRequiredService<IMediator>();\n        mediator.GetType().ShouldBe(typeof(MyCustomMediator));\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/DerivingRequestsTests.cs",
    "content": "﻿using System;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\nusing Shouldly;\nusing Xunit;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\npublic class DerivingRequestsTests\n{\n    private readonly IServiceProvider _provider;\n    private readonly IMediator _mediator;\n\n    public DerivingRequestsTests()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining(typeof(Ping)));\n        _provider = services.BuildServiceProvider();\n        _mediator = _provider.GetRequiredService<IMediator>();\n    }\n\n    [Fact]\n    public async Task ShouldReturnPingPong()\n    {\n        Pong pong = await _mediator.Send(new Ping() { Message = \"Ping\" });\n        pong.Message.ShouldBe(\"Ping Pong\");\n    }\n\n    [Fact]\n    public async Task ShouldReturnDerivedPingPong()\n    {\n        Pong pong = await _mediator.Send(new DerivedPing() { Message = \"Ping\" });\n        pong.Message.ShouldBe(\"DerivedPing Pong\");\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/DuplicateAssemblyResolutionTests.cs",
    "content": "﻿using Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Linq;\nusing Shouldly;\nusing Xunit;\n\npublic class DuplicateAssemblyResolutionTests\n{\n    private readonly IServiceProvider _provider;\n\n    public DuplicateAssemblyResolutionTests()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly, typeof(Ping).Assembly));\n        _provider = services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public void ShouldResolveNotificationHandlersOnlyOnce()\n    {\n        _provider.GetServices<INotificationHandler<Pinged>>().Count().ShouldBe(4);\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/Handlers.cs",
    "content": "﻿using System;\nusing System.Runtime.CompilerServices;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests\n{\n    using System.Collections.Generic;\n    using System.Threading;\n    using System.Threading.Tasks;\n\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; init; }\n        public Action<Ping>? ThrowAction { get; init; }\n    }\n\n    public class DerivedPing : Ping\n    {\n    }\n\n    public class Pong\n    {\n        public string? Message { get; init; }\n    }\n\n    public class Zing : IRequest<Zong>\n    {\n        public string? Message { get; init; }\n    }\n\n    public class Zong\n    {\n        public string? Message { get; init; }\n    }\n\n    public class Ding : IRequest\n    {\n        public string? Message { get; init; }\n    }\n\n    public class Pinged : INotification\n    {\n\n    }\n\n    class InternalPing : IRequest { }\n\n    public class StreamPing : IStreamRequest<Pong>\n    {\n        public string? Message { get; init; }\n    }\n\n    public class GenericHandler : INotificationHandler<INotification>\n    {\n        public Task Handle(INotification notification, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(0);\n        }\n    }\n\n    public class DingAsyncHandler : IRequestHandler<Ding>\n    {\n        public Task Handle(Ding message, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n\n    public class PingedHandler : INotificationHandler<Pinged>\n    {\n        public Task Handle(Pinged notification, CancellationToken cancellationToken)\n        {\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingedAlsoHandler : INotificationHandler<Pinged>\n    {\n        public Task Handle(Pinged notification, CancellationToken cancellationToken)\n        {\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingedAlsoOpenHandler<TNotification> : INotificationHandler<TNotification>\n        where TNotification : Pinged\n    {\n        public Task Handle(TNotification notification, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n\n    public class Logger\n    {\n        public IList<string> Messages { get; } = new List<string>();\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        private readonly Logger _logger;\n\n        public PingHandler(Logger logger)\n        {\n            _logger = logger;\n        }\n        public Task<Pong> Handle(Ping message, CancellationToken cancellationToken)\n        {\n            _logger.Messages.Add(\"Handler\");\n\n            message.ThrowAction?.Invoke(message);\n\n            return Task.FromResult(new Pong { Message = message.Message + \" Pong\" });\n        }\n    }\n\n    public class DerivedPingHandler : IRequestHandler<DerivedPing, Pong>\n    {\n        private readonly Logger _logger;\n\n        public DerivedPingHandler(Logger logger)\n        {\n            _logger = logger;\n        }\n        public Task<Pong> Handle(DerivedPing message, CancellationToken cancellationToken)\n        {\n            _logger.Messages.Add(\"Handler\");\n            return Task.FromResult(new Pong { Message = $\"Derived{message.Message} Pong\" });\n        }\n    }\n\n    public class ZingHandler : IRequestHandler<Zing, Zong>\n    {\n        private readonly Logger _output;\n\n        public ZingHandler(Logger output)\n        {\n            _output = output;\n        }\n        public Task<Zong> Handle(Zing message, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            return Task.FromResult(new Zong { Message = message.Message + \" Zong\" });\n        }\n    }\n\n    public class PingStreamHandler : IStreamRequestHandler<StreamPing, Pong>\n    {\n        private readonly Logger _output;\n\n        public PingStreamHandler(Logger output)\n        {\n            _output = output;\n        }\n        public async IAsyncEnumerable<Pong> Handle(StreamPing request, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            yield return await Task.Run(() => new Pong { Message = request.Message + \" Pang\" }, cancellationToken);\n        }\n    }\n\n\n    public class DuplicateTest : IRequest<string> { }\n    public class DuplicateHandler1 : IRequestHandler<DuplicateTest, string>\n    {\n        public Task<string> Handle(DuplicateTest message, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(nameof(DuplicateHandler1));\n        }\n    }\n\n    public class DuplicateHandler2 : IRequestHandler<DuplicateTest, string>\n    {\n        public Task<string> Handle(DuplicateTest message, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(nameof(DuplicateHandler2));\n        }\n    }\n\n    class InternalPingHandler : IRequestHandler<InternalPing>\n    {\n        public Task Handle(InternalPing request, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n\n    class MyCustomMediator : IMediator\n    {\n        public Task<object?> Send(object request, CancellationToken cancellationToken = new())\n        {\n            throw new System.NotImplementedException();\n        }\n\n        public IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamRequest<TResponse> request,\n            CancellationToken cancellationToken = new())\n        {\n            throw new NotImplementedException();\n        }\n\n        public IAsyncEnumerable<object?> CreateStream(object request, CancellationToken cancellationToken = new())\n        {\n            throw new NotImplementedException();\n        }\n\n        public Task Publish(object notification, CancellationToken cancellationToken = new())\n        {\n            throw new System.NotImplementedException();\n        }\n\n        public Task Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification\n        {\n            throw new System.NotImplementedException();\n        }\n\n        public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default)\n        {\n            throw new System.NotImplementedException();\n        }\n        public Task Send<TRequest>(TRequest request, CancellationToken cancellationToken = default)\n            where TRequest : IRequest\n        {\n            throw new System.NotImplementedException();\n        }\n    }\n\n    interface ITypeArgument { }\n    class ConcreteTypeArgument : ITypeArgument { }\n    class OpenGenericVoidRequest<T> : IRequest\n        where T : class, ITypeArgument\n    { }\n    class OpenGenericVoidRequestHandler<T> : IRequestHandler<OpenGenericVoidRequest<T>>\n        where T : class, ITypeArgument\n    {\n        public Task Handle(OpenGenericVoidRequest<T> request, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n    class OpenGenericReturnTypeRequest<T> : IRequest<string>\n        where T : class, ITypeArgument\n    { }\n    class OpenGenericReturnTypeRequestHandler<T> : IRequestHandler<OpenGenericReturnTypeRequest<T>, string>\n        where T : class, ITypeArgument\n    {\n        public Task<string> Handle(OpenGenericReturnTypeRequest<T> request, CancellationToken cancellationToken) => Task.FromResult(nameof(request));\n    }\n\n    public class GenericPing<T> : IRequest<T>\n        where T : Pong\n    {\n        public T? Pong { get; set; }\n    }\n\n    public class GenericPingHandler<T> : IRequestHandler<GenericPing<T>, T>\n        where T : Pong\n    {\n        public Task<T> Handle(GenericPing<T> request, CancellationToken cancellationToken) => Task.FromResult(request.Pong!);\n    }\n\n    public class VoidGenericPing<T> : IRequest\n        where T : Pong\n    { }\n\n    public class VoidGenericPingHandler<T> : IRequestHandler<VoidGenericPing<T>>\n        where T : Pong\n    {\n        public Task Handle(VoidGenericPing<T> request, CancellationToken cancellationToken) => Task.CompletedTask;\n    }\n\n}\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests.Included\n{\n    using System.Threading;\n    using System.Threading.Tasks;\n\n    public class Foo : IRequest<Bar>\n    {\n        public string? Message { get; init; }\n        public Action<Foo>? ThrowAction { get; init; }\n    }\n\n    public class Bar\n    {\n        public string? Message { get; init; }\n    }\n\n    public class FooHandler : IRequestHandler<Foo, Bar>\n    {\n        private readonly Logger _logger;\n\n        public FooHandler(Logger logger)\n        {\n            _logger = logger;\n        }\n        public Task<Bar> Handle(Foo message, CancellationToken cancellationToken)\n        {\n            _logger.Messages.Add(\"Handler\");\n\n            message.ThrowAction?.Invoke(message);\n\n            return Task.FromResult(new Bar { Message = message.Message + \" Bar\" });\n        }\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/Issue1118Tests.cs",
    "content": "using System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Microsoft.Extensions.DependencyInjection;\nusing Shouldly;\nusing Xunit;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\n/// <summary>\n/// Regression tests for https://github.com/LuckyPennySoftware/MediatR/issues/1118\n///\n/// When E2 derives from E1, a handler for E1 (C1) would be called twice when publishing E2\n/// because some DI containers that support variance (e.g. DryIoc) return C1 both from\n/// the explicit INotificationHandler&lt;E2&gt; registration AND from their own contravariant\n/// resolution of INotificationHandler&lt;E1&gt;.\n/// </summary>\npublic class Issue1118Tests\n{\n    public class CallLog\n    {\n        public List<string> Entries { get; } = new();\n    }\n\n    public class BaseEvent : INotification { }\n\n    public class DerivedEvent : BaseEvent { }\n\n    // IServiceProvider is always injectable, so CallLog becomes an optional soft dependency.\n    // This prevents PipelineTests (which uses ValidateOnBuild=true on the same assembly) from\n    // failing due to CallLog not being registered in its container.\n    public class BaseEventHandler : INotificationHandler<BaseEvent>\n    {\n        private readonly IServiceProvider _serviceProvider;\n\n        public BaseEventHandler(IServiceProvider serviceProvider)\n            => _serviceProvider = serviceProvider;\n\n        public Task Handle(BaseEvent notification, CancellationToken cancellationToken)\n        {\n            _serviceProvider.GetService<CallLog>()?.Entries.Add($\"BaseEventHandler:{notification.GetType().Name}\");\n            return Task.CompletedTask;\n        }\n    }\n\n    public class DerivedEventHandler : INotificationHandler<DerivedEvent>\n    {\n        private readonly IServiceProvider _serviceProvider;\n\n        public DerivedEventHandler(IServiceProvider serviceProvider)\n            => _serviceProvider = serviceProvider;\n\n        public Task Handle(DerivedEvent notification, CancellationToken cancellationToken)\n        {\n            _serviceProvider.GetService<CallLog>()?.Entries.Add($\"DerivedEventHandler:{notification.GetType().Name}\");\n            return Task.CompletedTask;\n        }\n    }\n\n    private static IServiceProvider BuildProvider()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton<CallLog>();\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Issue1118Tests).Assembly));\n        return services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public async Task Publishing_BaseEvent_Should_Call_BaseEventHandler_Once()\n    {\n        var provider = BuildProvider();\n        var log = provider.GetRequiredService<CallLog>();\n\n        await provider.GetRequiredService<IPublisher>().Publish(new BaseEvent());\n\n        log.Entries.Count(e => e.StartsWith(\"BaseEventHandler\")).ShouldBe(1);\n    }\n\n    [Fact]\n    public async Task Publishing_DerivedEvent_Should_Call_BaseEventHandler_ExactlyOnce()\n    {\n        var provider = BuildProvider();\n        var log = provider.GetRequiredService<CallLog>();\n\n        await provider.GetRequiredService<IPublisher>().Publish(new DerivedEvent());\n\n        log.Entries.Count(e => e.StartsWith(\"BaseEventHandler\")).ShouldBe(1,\n            \"BaseEventHandler should be called exactly once for DerivedEvent, not duplicated\");\n    }\n\n    [Fact]\n    public async Task Publishing_DerivedEvent_Should_Call_DerivedEventHandler_Once()\n    {\n        var provider = BuildProvider();\n        var log = provider.GetRequiredService<CallLog>();\n\n        await provider.GetRequiredService<IPublisher>().Publish(new DerivedEvent());\n\n        log.Entries.Count(e => e.StartsWith(\"DerivedEventHandler\")).ShouldBe(1);\n    }\n}\n"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/NotificationPublisherTests.cs",
    "content": "﻿using Microsoft.Extensions.DependencyInjection;\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.NotificationPublishers;\nusing Shouldly;\nusing Xunit;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\npublic class NotificationPublisherTests\n{\n    public class MockPublisher : INotificationPublisher\n    {\n        public int CallCount { get; set; }\n\n        public async Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)\n        {\n            foreach (var handlerExecutor in handlerExecutors)\n            {\n                await handlerExecutor.HandlerCallback(notification, cancellationToken);\n                CallCount++;\n            }\n        }\n    }\n\n    [Fact]\n    public void ShouldResolveDefaultPublisher()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n        });\n\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetService<IMediator>();\n\n        mediator.ShouldNotBeNull();\n\n        var publisher = provider.GetService<INotificationPublisher>();\n\n        publisher.ShouldNotBeNull();\n    }\n\n    [Fact]\n    public async Task ShouldSubstitutePublisherInstance()\n    {\n        var publisher = new MockPublisher();\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n            cfg.NotificationPublisher = publisher;\n        });\n\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetService<IMediator>();\n\n        mediator.ShouldNotBeNull();\n\n        await mediator.Publish(new Pinged());\n        \n        publisher.CallCount.ShouldBeGreaterThan(0);\n    }\n\n    [Fact]\n    public async Task ShouldSubstitutePublisherServiceType()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n            cfg.NotificationPublisherType = typeof(MockPublisher);\n            cfg.Lifetime = ServiceLifetime.Singleton;\n        });\n\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetService<IMediator>();\n        var publisher = provider.GetService<INotificationPublisher>();\n\n        mediator.ShouldNotBeNull();\n        publisher.ShouldNotBeNull();\n\n        await mediator.Publish(new Pinged());\n\n        var mock = publisher.ShouldBeOfType<MockPublisher>();\n\n        mock.CallCount.ShouldBeGreaterThan(0);\n    }\n\n    [Fact]\n    public async Task ShouldSubstitutePublisherServiceTypeWithWhenAll()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining(typeof(CustomMediatorTests));\n            cfg.NotificationPublisherType = typeof(TaskWhenAllPublisher);\n            cfg.Lifetime = ServiceLifetime.Singleton;\n        });\n\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetService<IMediator>();\n        var publisher = provider.GetService<INotificationPublisher>();\n\n        mediator.ShouldNotBeNull();\n        publisher.ShouldNotBeNull();\n\n        await Should.NotThrowAsync(mediator.Publish(new Pinged()));\n\n        publisher.ShouldBeOfType<TaskWhenAllPublisher>();\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/PipeLineMultiCallToConstructorTest.cs",
    "content": "﻿using System.Threading;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System.Reflection;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class PipelineMultiCallToConstructorTests\n{\n    public class ConstructorTestBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : IRequest<TResponse>\n    {\n        private readonly Logger _output;\n\n        public ConstructorTestBehavior(Logger output) => _output = output;\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"ConstructorTestBehavior before\");\n            var response = await next();\n            _output.Messages.Add(\"ConstructorTestBehavior after\");\n\n            return response;\n        }\n    }\n\n    public class ConstructorTestRequest : IRequest<ConstructorTestResponse>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class ConstructorTestResponse\n    {\n        public string? Message { get; set; }\n    }\n\n    public class ConstructorTestHandler : IRequestHandler<ConstructorTestRequest, ConstructorTestResponse>\n    {\n\n        private static volatile object _lockObject = new();\n        private readonly Logger _logger;\n        private static int _constructorCallCount;\n\n        public static int ConstructorCallCount => _constructorCallCount;\n\n        public static void ResetCallCount()\n        {\n            lock (_lockObject)\n            {\n                _constructorCallCount = 0;\n            }\n        }\n\n        public ConstructorTestHandler(Logger logger)\n        {\n            _logger = logger;\n            lock (_lockObject)\n            {\n                _constructorCallCount++;\n            }\n        }\n\n        public Task<ConstructorTestResponse> Handle(ConstructorTestRequest request, CancellationToken cancellationToken)\n        {\n            _logger.Messages.Add(\"Handler\");\n            return Task.FromResult(new ConstructorTestResponse { Message = request.Message + \" ConstructorPong\" });\n        }\n    }\n\n    [Fact]\n    public async Task Should_not_call_constructor_multiple_times_when_using_a_pipeline()\n    {\n        ConstructorTestHandler.ResetCallCount();\n        ConstructorTestHandler.ConstructorCallCount.ShouldBe(0);\n\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ConstructorTestBehavior<,>));\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddOpenBehavior(typeof(ConstructorTestBehavior<,>));\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new ConstructorTestRequest { Message = \"ConstructorPing\" });\n\n        response.Message.ShouldBe(\"ConstructorPing ConstructorPong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"ConstructorTestBehavior before\",\n            \"Handler\",\n            \"ConstructorTestBehavior after\"\n        });\n        ConstructorTestHandler.ConstructorCallCount.ShouldBe(1);\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/PipelineTests.cs",
    "content": "﻿using System.Runtime.CompilerServices;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class PipelineTests\n{\n    public class OuterBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            var response = await next();\n            _output.Messages.Add(\"Outer after\");\n\n            return response;\n        }\n    }\n\n    public class InnerBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            var response = await next();\n            _output.Messages.Add(\"Inner after\");\n\n            return response;\n        }\n    }\n   \n    public class OuterStreamBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public OuterStreamBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            await foreach (var item in next().WithCancellation(cancellationToken))\n            {\n                yield return item;\n            }\n            _output.Messages.Add(\"Outer after\");\n        }\n    }\n\n    public class InnerStreamBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public InnerStreamBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            await foreach (var item in next().WithCancellation(cancellationToken))\n            {\n                yield return item;\n            }\n            _output.Messages.Add(\"Inner after\");\n        }\n    }\n\n    public class InnerBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner generic before\");\n            var response = await next();\n            _output.Messages.Add(\"Inner generic after\");\n\n            return response;\n        }\n    }\n\n    public class OuterBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer generic before\");\n            var response = await next();\n            _output.Messages.Add(\"Outer generic after\");\n\n            return response;\n        }\n    }\n\n    public class ConstrainedBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n        where TResponse : Pong\n    {\n        private readonly Logger _output;\n\n        public ConstrainedBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Constrained before\");\n            var response = await next();\n            _output.Messages.Add(\"Constrained after\");\n\n            return response;\n        }\n    }\n\n    public class FirstPreProcessor<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public FirstPreProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(TRequest request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"First pre processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class FirstConcretePreProcessor : IRequestPreProcessor<Ping>\n    {\n        private readonly Logger _output;\n\n        public FirstConcretePreProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(Ping request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"First concrete pre processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class NextPreProcessor<TRequest> : IRequestPreProcessor<TRequest> where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public NextPreProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(TRequest request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Next pre processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class NextConcretePreProcessor : IRequestPreProcessor<Ping>\n    {\n        private readonly Logger _output;\n\n        public NextConcretePreProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(Ping request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Next concrete pre processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class FirstPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public FirstPostProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(TRequest request, TResponse response, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"First post processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class FirstConcretePostProcessor : IRequestPostProcessor<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public FirstConcretePostProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(Ping request, Pong response, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"First concrete post processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class NextPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public NextPostProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(TRequest request, TResponse response, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Next post processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class NextConcretePostProcessor : IRequestPostProcessor<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public NextConcretePostProcessor(Logger output)\n        {\n            _output = output;\n        }\n        public Task Process(Ping request, Pong response, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Next concrete post processor\");\n            return Task.FromResult(0);\n        }\n    }\n\n    public class PingPongGenericExceptionAction : IRequestExceptionAction<Ping, Exception>\n    {\n        private readonly Logger _output;\n\n        public PingPongGenericExceptionAction(Logger output) => _output = output;\n\n        public Task Execute(Ping request, Exception exception, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Logging generic exception\");\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongApplicationExceptionAction : IRequestExceptionAction<Ping, ApplicationException>\n    {\n        private readonly Logger _output;\n\n        public PingPongApplicationExceptionAction(Logger output) => _output = output;\n\n        public Task Execute(Ping request, ApplicationException exception, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Logging ApplicationException exception\");\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionActionForType1 : IRequestExceptionAction<Ping, SystemException>\n    {\n        private readonly Logger _output;\n\n        public PingPongExceptionActionForType1(Logger output) => _output = output;\n\n        public Task Execute(Ping request, SystemException exception, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Logging exception 1\");\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionActionForType2 : IRequestExceptionAction<Ping, SystemException>\n    {\n        private readonly Logger _output;\n\n        public PingPongExceptionActionForType2(Logger output) => _output = output;\n\n        public Task Execute(Ping request, SystemException exception, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Logging exception 2\");\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionHandlerForType : IRequestExceptionHandler<Ping, Pong, ApplicationException>\n    {\n        public Task Handle(Ping request, ApplicationException exception, RequestExceptionHandlerState<Pong> state, CancellationToken cancellationToken)\n        {\n            state.SetHandled(new Pong { Message = exception.Message + \" Handled by Specific Type\" });\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongGenericExceptionHandler : IRequestExceptionHandler<Ping, Pong, Exception>\n    {\n        private readonly Logger _output;\n\n        public PingPongGenericExceptionHandler(Logger output) => _output = output;\n\n        public Task Handle(Ping request, Exception exception, RequestExceptionHandlerState<Pong> state, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(exception.Message + \" Logged by Generic Type\");\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class NotAnOpenBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken) => next();\n    }\n\n    public class ThrowingBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken) => throw new Exception(request.Message);\n    }\n\n    public class NotAnOpenStreamBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        public IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, CancellationToken cancellationToken) => next();\n    }\n\n    public class OpenBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) => next();\n    }\n\n    public class OpenStreamBehavior<TRequest, TResponse> : IStreamPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, CancellationToken cancellationToken) => next();\n    }\n\n    public class MultiOpenBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>, IStreamPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) => next();\n\n        public IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, CancellationToken cancellationToken) => next();\n    }\n\n    [Fact]\n    public async Task Should_wrap_with_behavior()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddBehavior<IPipelineBehavior<Ping, Pong>, OuterBehavior>();\n            cfg.AddBehavior<IPipelineBehavior<Ping, Pong>, InnerBehavior>();\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n\n    [Fact]\n    public async Task Should_wrap_generics_with_behavior()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            // Call these registration methods multiple times to prove we don't register a service if it is already registered\n            for (var i = 0; i < 3; i++)\n            {\n                cfg.AddOpenBehavior(typeof(OuterBehavior<,>));\n                cfg.AddOpenBehavior(typeof(InnerBehavior<,>));\n                cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            }\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n            \n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact]\n    public async Task Should_register_pre_and_post_processors()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddRequestPreProcessor<IRequestPreProcessor<Ping>, FirstConcretePreProcessor>();\n            cfg.AddRequestPreProcessor<IRequestPreProcessor<Ping>, NextConcretePreProcessor>();\n            cfg.AddOpenRequestPreProcessor(typeof(FirstPreProcessor<>));\n            cfg.AddOpenRequestPreProcessor(typeof(NextPreProcessor<>));\n            cfg.AddRequestPostProcessor<IRequestPostProcessor<Ping, Pong>, FirstConcretePostProcessor>();\n            cfg.AddRequestPostProcessor<IRequestPostProcessor<Ping, Pong>, NextConcretePostProcessor>();\n            cfg.AddOpenRequestPostProcessor(typeof(FirstPostProcessor<,>));\n            cfg.AddOpenRequestPostProcessor(typeof(NextPostProcessor<,>));\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"First concrete pre processor\",\n            \"Next concrete pre processor\",\n            \"First pre processor\",\n            \"Next pre processor\",\n            \"Handler\",\n            \"First concrete post processor\",\n            \"Next concrete post processor\",\n            \"First post processor\",\n            \"Next post processor\",\n        });\n    }\n\n    [Fact]\n    public async Task Should_pick_up_specific_exception_behaviors()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(output);\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly));\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping {Message = \"Ping\", ThrowAction = msg => throw new ApplicationException(msg.Message + \" Thrown\")});\n\n        response.Message.ShouldBe(\"Ping Thrown Handled by Specific Type\");\n        output.Messages.ShouldNotContain(\"Logging ApplicationException exception\");\n    }\n\n    [Fact]\n    public void Should_pick_up_base_exception_behaviors()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly));\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        Should.Throw<Exception>(async () => await mediator.Send(new Ping {Message = \"Ping\", ThrowAction = msg => throw new Exception(msg.Message + \" Thrown\")}));\n\n        output.Messages.ShouldContain(\"Ping Thrown Logged by Generic Type\");\n        output.Messages.ShouldContain(\"Logging generic exception\");\n    }\n\n    [Fact]\n    public void Should_handle_exceptions_from_behaviors()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddBehavior<ThrowingBehavior>();\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        Should.Throw<Exception>(async () => await mediator.Send(new Ping {Message = \"Ping\"}));\n\n        output.Messages.ShouldContain(\"Ping Logged by Generic Type\");\n        output.Messages.ShouldContain(\"Logging generic exception\");\n    }\n\n    [Fact]\n    public void Should_pick_up_exception_actions()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(output);\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly));\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        Should.Throw<SystemException>(async () => await mediator.Send(new Ping {Message = \"Ping\", ThrowAction = msg => throw new SystemException(msg.Message + \" Thrown\")}));\n\n        output.Messages.ShouldContain(\"Logging exception 1\");\n        output.Messages.ShouldContain(\"Logging exception 2\");\n    }\n\n    [Fact]\n    public async Task Should_handle_constrained_generics()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddOpenBehavior(typeof(OuterBehavior<,>));\n            cfg.AddOpenBehavior(typeof(InnerBehavior<,>));\n            cfg.AddOpenBehavior(typeof(ConstrainedBehavior<,>));\n            cfg.AddRequestPreProcessor<IRequestPreProcessor<Ping>, FirstConcretePreProcessor>();\n            cfg.AddRequestPreProcessor<IRequestPreProcessor<Ping>, NextConcretePreProcessor>();\n            cfg.AddOpenRequestPreProcessor(typeof(FirstPreProcessor<>));\n            cfg.AddOpenRequestPreProcessor(typeof(NextPreProcessor<>));\n            cfg.AddRequestPostProcessor<IRequestPostProcessor<Ping, Pong>, FirstConcretePostProcessor>();\n            cfg.AddRequestPostProcessor<IRequestPostProcessor<Ping, Pong>, NextConcretePostProcessor>();\n            cfg.AddOpenRequestPostProcessor(typeof(FirstPostProcessor<,>));\n            cfg.AddOpenRequestPostProcessor(typeof(NextPostProcessor<,>));\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"First concrete pre processor\",\n            \"Next concrete pre processor\",\n            \"First pre processor\",\n            \"Next pre processor\",\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Constrained before\",\n            \"Handler\",\n            \"Constrained after\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n            \"First concrete post processor\",\n            \"Next concrete post processor\",\n            \"First post processor\",\n            \"Next post processor\"\n        });\n\n        output.Messages.Clear();\n\n        var zingResponse = await mediator.Send(new Zing { Message = \"Zing\" });\n\n        zingResponse.Message.ShouldBe(\"Zing Zong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"First pre processor\",\n            \"Next pre processor\",\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n            \"First post processor\",\n            \"Next post processor\"\n        });\n    }\n\n    [Fact]\n    public void Should_throw_when_adding_non_open_behavior()\n    {\n        Should.Throw<InvalidOperationException>(() => new MediatRServiceConfiguration().AddOpenBehavior(typeof(NotAnOpenBehavior)));\n    }\n\n    [Fact]\n    public void Should_throw_when_adding_non_open_stream_behavior()\n    {\n        Should.Throw<InvalidOperationException>(() => new MediatRServiceConfiguration().AddOpenBehavior(typeof(NotAnOpenStreamBehavior)));\n    }\n\n    [Fact]\n    public void Should_throw_when_adding_random_generic_type_as_open_behavior()\n    {\n        Should.Throw<InvalidOperationException>(() => new MediatRServiceConfiguration().AddOpenBehavior(typeof(List<string>)));\n    }\n\n    [Fact]\n    public void Should_handle_open_behavior_registration()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddOpenBehavior(typeof(OpenBehavior<,>));\n        cfg.AddOpenStreamBehavior(typeof(OpenStreamBehavior<,>));\n\n        cfg.BehaviorsToRegister.Count.ShouldBe(1);\n        cfg.StreamBehaviorsToRegister.Count.ShouldBe(1);\n\n        cfg.BehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IPipelineBehavior<,>));\n        cfg.BehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(OpenBehavior<,>));\n        cfg.BehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n\n        cfg.StreamBehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IStreamPipelineBehavior<,>));\n        cfg.StreamBehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(OpenStreamBehavior<,>));\n        cfg.StreamBehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n\n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n    \n    [Fact]\n    public void Should_handle_inferred_behavior_registration()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddBehavior<InnerBehavior>();\n        cfg.AddBehavior(typeof(OuterBehavior));\n\n        cfg.BehaviorsToRegister.Count.ShouldBe(2);\n\n        cfg.BehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IPipelineBehavior<Ping, Pong>));\n        cfg.BehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(InnerBehavior));\n        cfg.BehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        cfg.BehaviorsToRegister[1].ServiceType.ShouldBe(typeof(IPipelineBehavior<Ping, Pong>));\n        cfg.BehaviorsToRegister[1].ImplementationType.ShouldBe(typeof(OuterBehavior));\n        cfg.BehaviorsToRegister[1].ImplementationFactory.ShouldBeNull();\n        cfg.BehaviorsToRegister[1].ImplementationInstance.ShouldBeNull();\n        cfg.BehaviorsToRegister[1].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        \n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n\n        \n    [Fact]\n    public void Should_handle_inferred_stream_behavior_registration()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddStreamBehavior<InnerStreamBehavior>();\n        cfg.AddStreamBehavior(typeof(OuterStreamBehavior));\n\n        cfg.StreamBehaviorsToRegister.Count.ShouldBe(2);\n\n        cfg.StreamBehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IStreamPipelineBehavior<Ping, Pong>));\n        cfg.StreamBehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(InnerStreamBehavior));\n        cfg.StreamBehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        cfg.StreamBehaviorsToRegister[1].ServiceType.ShouldBe(typeof(IStreamPipelineBehavior<Ping, Pong>));\n        cfg.StreamBehaviorsToRegister[1].ImplementationType.ShouldBe(typeof(OuterStreamBehavior));\n        cfg.StreamBehaviorsToRegister[1].ImplementationFactory.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[1].ImplementationInstance.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[1].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        \n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n    \n    [Fact]\n    public void Should_handle_inferred_pre_processor_registration()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddRequestPreProcessor<FirstConcretePreProcessor>();\n        cfg.AddRequestPreProcessor(typeof(NextConcretePreProcessor));\n\n        cfg.RequestPreProcessorsToRegister.Count.ShouldBe(2);\n\n        cfg.RequestPreProcessorsToRegister[0].ServiceType.ShouldBe(typeof(IRequestPreProcessor<Ping>));\n        cfg.RequestPreProcessorsToRegister[0].ImplementationType.ShouldBe(typeof(FirstConcretePreProcessor));\n        cfg.RequestPreProcessorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.RequestPreProcessorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.RequestPreProcessorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        cfg.RequestPreProcessorsToRegister[1].ServiceType.ShouldBe(typeof(IRequestPreProcessor<Ping>));\n        cfg.RequestPreProcessorsToRegister[1].ImplementationType.ShouldBe(typeof(NextConcretePreProcessor));\n        cfg.RequestPreProcessorsToRegister[1].ImplementationFactory.ShouldBeNull();\n        cfg.RequestPreProcessorsToRegister[1].ImplementationInstance.ShouldBeNull();\n        cfg.RequestPreProcessorsToRegister[1].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        \n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n    \n    [Fact]\n    public void Should_handle_inferred_post_processor_registration()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddRequestPostProcessor<FirstConcretePostProcessor>();\n        cfg.AddRequestPostProcessor(typeof(NextConcretePostProcessor));\n\n        cfg.RequestPostProcessorsToRegister.Count.ShouldBe(2);\n\n        cfg.RequestPostProcessorsToRegister[0].ServiceType.ShouldBe(typeof(IRequestPostProcessor<Ping, Pong>));\n        cfg.RequestPostProcessorsToRegister[0].ImplementationType.ShouldBe(typeof(FirstConcretePostProcessor));\n        cfg.RequestPostProcessorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.RequestPostProcessorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.RequestPostProcessorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        cfg.RequestPostProcessorsToRegister[1].ServiceType.ShouldBe(typeof(IRequestPostProcessor<Ping, Pong>));\n        cfg.RequestPostProcessorsToRegister[1].ImplementationType.ShouldBe(typeof(NextConcretePostProcessor));\n        cfg.RequestPostProcessorsToRegister[1].ImplementationFactory.ShouldBeNull();\n        cfg.RequestPostProcessorsToRegister[1].ImplementationInstance.ShouldBeNull();\n        cfg.RequestPostProcessorsToRegister[1].Lifetime.ShouldBe(ServiceLifetime.Transient);\n        \n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n    \n    [Fact]\n    public void Should_handle_open_behaviors_registration_from_a_single_type()\n    {\n        var cfg = new MediatRServiceConfiguration();\n        cfg.AddOpenBehavior(typeof(MultiOpenBehavior<,>), ServiceLifetime.Singleton);\n        cfg.AddOpenStreamBehavior(typeof(MultiOpenBehavior<,>), ServiceLifetime.Singleton);\n\n        cfg.BehaviorsToRegister.Count.ShouldBe(1);\n        cfg.StreamBehaviorsToRegister.Count.ShouldBe(1);\n\n        cfg.BehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IPipelineBehavior<,>));\n        cfg.BehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(MultiOpenBehavior<,>));\n        cfg.BehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.BehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Singleton);\n\n        cfg.StreamBehaviorsToRegister[0].ServiceType.ShouldBe(typeof(IStreamPipelineBehavior<,>));\n        cfg.StreamBehaviorsToRegister[0].ImplementationType.ShouldBe(typeof(MultiOpenBehavior<,>));\n        cfg.StreamBehaviorsToRegister[0].ImplementationFactory.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].ImplementationInstance.ShouldBeNull();\n        cfg.StreamBehaviorsToRegister[0].Lifetime.ShouldBe(ServiceLifetime.Singleton);\n        \n        var services = new ServiceCollection();\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        Should.NotThrow(() =>\n        {\n            services.AddMediatR(cfg);\n            services.BuildServiceProvider();\n        });\n    }\n\n    [Fact]\n    public void Should_auto_register_processors_when_configured_including_all_concrete_types()\n    {\n        var cfg = new MediatRServiceConfiguration\n        {\n            AutoRegisterRequestProcessors = true\n        };\n\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n\n        cfg.RegisterServicesFromAssemblyContaining<Ping>();\n\n        services.AddMediatR(cfg);\n\n        var provider = services.BuildServiceProvider();\n\n        var preProcessors = provider.GetServices(typeof(IRequestPreProcessor<Ping>)).ToList();\n        preProcessors.Count.ShouldBeGreaterThan(0);\n        preProcessors.ShouldContain(p => p != null && p.GetType() == typeof(FirstConcretePreProcessor));\n        preProcessors.ShouldContain(p => p != null && p.GetType() == typeof(NextConcretePreProcessor));\n\n        var postProcessors = provider.GetServices(typeof(IRequestPostProcessor<Ping, Pong>)).ToList();\n        postProcessors.Count.ShouldBeGreaterThan(0);\n        postProcessors.ShouldContain(p => p != null && p.GetType() == typeof(FirstConcretePostProcessor));\n        postProcessors.ShouldContain(p => p != null && p.GetType() == typeof(NextConcretePostProcessor));\n    }\n\n\n    public sealed record FooRequest : IRequest;\n    \n    public interface IBlogger<T>\n    {\n        IList<string> Messages { get; }\n    }\n\n    public class Blogger<T> : IBlogger<T>\n    {\n        private readonly Logger _logger;\n\n        public Blogger(Logger logger)\n        {\n            _logger = logger;\n        }\n\n        public IList<string> Messages => _logger.Messages;\n    }\n\n    public sealed class FooRequestHandler : IRequestHandler<FooRequest> {\n        public FooRequestHandler(IBlogger<FooRequestHandler> logger)\n        {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<FooRequestHandler> logger;\n\n        public Task Handle(FooRequest request, CancellationToken cancellationToken) {\n            logger.Messages.Add(\"Invoked Handler\");\n            return Task.CompletedTask;\n        }\n    }\n\n    sealed class ClosedBehavior : IPipelineBehavior<FooRequest, Unit> {\n        public ClosedBehavior(IBlogger<ClosedBehavior> logger)\n        {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<ClosedBehavior> logger;\n\n        public Task<Unit> Handle(FooRequest request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken) {\n            logger.Messages.Add(\"Invoked Closed Behavior\");\n            return next();\n        }\n    }\n\n    sealed class Open2Behavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull {\n        public Open2Behavior(IBlogger<Open2Behavior<TRequest, TResponse>> logger) {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<Open2Behavior<TRequest, TResponse>> logger;\n\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) {\n            logger.Messages.Add(\"Invoked Open Behavior\");\n            return next();\n        }\n    }\n    [Fact]\n    public async Task Should_register_correctly()\n    {\n        var services = new ServiceCollection();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining<FooRequest>();\n            cfg.AddBehavior<ClosedBehavior>();\n            cfg.AddOpenBehavior(typeof(Open2Behavior<,>));\n        });\n        services.AddFakeLogging();\n        var logger = new Logger();\n        services.AddSingleton(logger);\n        services.AddSingleton(new MediatR.Tests.PipelineTests.Logger());\n        services.AddSingleton(new MediatR.Tests.StreamPipelineTests.Logger());\n        services.AddSingleton(new MediatR.Tests.SendTests.Dependency());\n        services.AddSingleton<System.IO.TextWriter>(new System.IO.StringWriter());\n        services.AddTransient(typeof(IBlogger<>), typeof(Blogger<>));\n        var provider = services.BuildServiceProvider(new ServiceProviderOptions\n        {\n            ValidateOnBuild = true\n        });\n\n        var mediator = provider.GetRequiredService<IMediator>();\n        var request = new FooRequest();\n        await mediator.Send(request);\n        \n        logger.Messages.ShouldBe(new []\n        {\n            \"Invoked Closed Behavior\",\n            \"Invoked Open Behavior\",\n            \"Invoked Handler\",\n        });\n    }\n\n\n    #region OpenBehaviorsForMultipleRegistration\n    sealed class OpenBehaviorMultipleRegistration0<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public OpenBehaviorMultipleRegistration0(IBlogger<OpenBehaviorMultipleRegistration0<TRequest, TResponse>> logger)\n        {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<OpenBehaviorMultipleRegistration0<TRequest, TResponse>> logger;\n\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            logger.Messages.Add(\"Invoked OpenBehaviorMultipleRegistration0\");\n            return next();\n        }\n    }\n    sealed class OpenBehaviorMultipleRegistration1<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public OpenBehaviorMultipleRegistration1(IBlogger<OpenBehaviorMultipleRegistration1<TRequest, TResponse>> logger)\n        {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<OpenBehaviorMultipleRegistration1<TRequest, TResponse>> logger;\n\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            logger.Messages.Add(\"Invoked OpenBehaviorMultipleRegistration1\");\n            return next();\n        }\n    }\n    sealed class OpenBehaviorMultipleRegistration2<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : notnull\n    {\n        public OpenBehaviorMultipleRegistration2(IBlogger<OpenBehaviorMultipleRegistration2<TRequest, TResponse>> logger)\n        {\n            this.logger = logger;\n        }\n\n        readonly IBlogger<OpenBehaviorMultipleRegistration2<TRequest, TResponse>> logger;\n\n        public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            logger.Messages.Add(\"Invoked OpenBehaviorMultipleRegistration2\");\n            return next();\n        }\n    }\n    #endregion OpenBehaviorsForMultipleRegistration\n\n    [Fact]\n    public async Task Should_register_open_behaviors_correctly()\n    {\n        var behaviorTypeList = new List<Type>\n        {\n            typeof(OpenBehaviorMultipleRegistration0<,>),\n            typeof(OpenBehaviorMultipleRegistration1<,>),\n            typeof(OpenBehaviorMultipleRegistration2<,>)\n        };\n        var services = new ServiceCollection();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining<FooRequest>();\n            cfg.AddOpenBehaviors(behaviorTypeList);\n        });\n        services.AddFakeLogging();\n        var logger = new Logger();\n        services.AddSingleton(logger);\n        services.AddSingleton(new MediatR.Tests.PipelineTests.Logger());\n        services.AddSingleton(new MediatR.Tests.StreamPipelineTests.Logger());\n        services.AddSingleton(new MediatR.Tests.SendTests.Dependency());\n        services.AddSingleton<System.IO.TextWriter>(new System.IO.StringWriter());\n        services.AddTransient(typeof(IBlogger<>), typeof(Blogger<>));\n        var provider = services.BuildServiceProvider(new ServiceProviderOptions\n        {\n            ValidateOnBuild = true\n        });\n\n        var mediator = provider.GetRequiredService<IMediator>();\n        var request = new FooRequest();\n        await mediator.Send(request);\n\n        logger.Messages.ShouldBe(new[]\n        {\n            \"Invoked OpenBehaviorMultipleRegistration0\",\n            \"Invoked OpenBehaviorMultipleRegistration1\",\n            \"Invoked OpenBehaviorMultipleRegistration2\",\n            \"Invoked Handler\",\n        });\n    }\n\n    // Types for nested generic response type behavior test\n    public class ListPing : IRequest<List<Pong>> { }\n\n    public class ListPingHandler : IRequestHandler<ListPing, List<Pong>>\n    {\n        private readonly Logger _output;\n        public ListPingHandler(Logger output) => _output = output;\n        public Task<List<Pong>> Handle(ListPing request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            return Task.FromResult(new List<Pong> { new() { Message = \"Pong\" } });\n        }\n    }\n\n    public class ListResponseBehavior<TRequest, TItem>\n        : IPipelineBehavior<TRequest, List<TItem>>\n        where TRequest : IRequest<List<TItem>>\n    {\n        private readonly Logger _output;\n        public ListResponseBehavior(Logger output) => _output = output;\n        public async Task<List<TItem>> Handle(TRequest request, RequestHandlerDelegate<List<TItem>> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Nested behavior before\");\n            var result = await next();\n            _output.Messages.Add(\"Nested behavior after\");\n            return result;\n        }\n    }\n\n    [Fact]\n    public async Task Should_apply_open_behavior_with_nested_generic_response_type()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(PipelineTests).Assembly);\n            cfg.AddOpenBehavior(typeof(ListResponseBehavior<,>));\n        });\n        var provider = services.BuildServiceProvider();\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var result = await mediator.Send(new ListPing());\n\n        result.ShouldNotBeEmpty();\n        output.Messages.ShouldBe(new[] { \"Nested behavior before\", \"Handler\", \"Nested behavior after\" });\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/StreamPipelineTests.cs",
    "content": "﻿using System.Runtime.CompilerServices;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Reflection;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class StreamPipelineTests\n{\n    public class OuterBehavior : IStreamPipelineBehavior<StreamPing, Pong>\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(StreamPing request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            await foreach (var response in next().WithCancellation(cancellationToken))\n            {\n                yield return response;\n            }\n            _output.Messages.Add(\"Outer after\");\n        }\n    }\n\n    public class InnerBehavior : IStreamPipelineBehavior<StreamPing, Pong>\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(StreamPing request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            await foreach (var response in next().WithCancellation(cancellationToken))\n            {\n                yield return response;\n            }\n            _output.Messages.Add(\"Inner after\");\n        }\n    }\n\n    [Fact]\n    public async Task Should_wrap_with_behavior()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(output);\n        services.AddTransient<IStreamPipelineBehavior<StreamPing, Pong>, OuterBehavior>();\n        services.AddTransient<IStreamPipelineBehavior<StreamPing, Pong>, InnerBehavior>();\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly));\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var stream = mediator.CreateStream(new StreamPing { Message = \"Ping\" });\n\n        await foreach (var response in stream)\n        {\n            response.Message.ShouldBe(\"Ping Pang\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n   \n    [Fact]\n    public async Task Should_register_and_wrap_with_behavior()\n    {\n        var output = new Logger();\n        IServiceCollection services = new ServiceCollection();\n        services.AddSingleton(output);\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssembly(typeof(Ping).Assembly);\n            cfg.AddStreamBehavior<IStreamPipelineBehavior<StreamPing, Pong>, OuterBehavior>();\n            cfg.AddStreamBehavior<IStreamPipelineBehavior<StreamPing, Pong>, InnerBehavior>();\n        });\n        var provider = services.BuildServiceProvider();\n\n        var mediator = provider.GetRequiredService<IMediator>();\n\n        var stream = mediator.CreateStream(new StreamPing { Message = \"Ping\" });\n\n        await foreach (var response in stream)\n        {\n            response.Message.ShouldBe(\"Ping Pang\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/TypeEvaluatorTests.cs",
    "content": "﻿using System.Linq;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing Included;\nusing MediatR.Pipeline;\nusing Shouldly;\nusing System;\nusing Xunit;\n\npublic class TypeEvaluatorTests\n{\n    private readonly IServiceProvider _provider;\n    private readonly IServiceCollection _services;\n\n\n    public TypeEvaluatorTests()\n    {\n        _services = new ServiceCollection();\n        _services.AddFakeLogging();\n        _services.AddSingleton(new Logger());\n        _services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining(typeof(Ping));\n            cfg.TypeEvaluator = t => t.Namespace == \"MediatR.Extensions.Microsoft.DependencyInjection.Tests.Included\";\n        });\n        _provider = _services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public void ShouldResolveMediator()\n    {\n        _provider.GetService<IMediator>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldOnlyResolveIncludedRequestHandlers()\n    {\n        _provider.GetService<IRequestHandler<Foo, Bar>>().ShouldNotBeNull();\n        _provider.GetService<IRequestHandler<Ping, Pong>>().ShouldBeNull();\n    }\n\n    [Fact]\n    public void ShouldNotRegisterUnNeededBehaviors()\n    {\n        _services.Any(service => service.ImplementationType == typeof(RequestPreProcessorBehavior<,>))\n            .ShouldBeFalse();\n        _services.Any(service => service.ImplementationType == typeof(RequestPostProcessorBehavior<,>))\n            .ShouldBeFalse();\n        _services.Any(service => service.ImplementationType == typeof(RequestExceptionActionProcessorBehavior<,>))\n            .ShouldBeFalse();\n        _services.Any(service => service.ImplementationType == typeof(RequestExceptionProcessorBehavior<,>))\n            .ShouldBeFalse();\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/MicrosoftExtensionsDI/TypeResolutionTests.cs",
    "content": "﻿using System.Collections.Generic;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Extensions.Microsoft.DependencyInjection.Tests;\n\nusing System;\nusing System.Linq;\nusing System.Reflection;\nusing MediatR.Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class TypeResolutionTests\n{\n    private readonly IServiceProvider _provider;\n\n    public TypeResolutionTests()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining(typeof(Ping)));\n        _provider = services.BuildServiceProvider();\n    }\n\n    [Fact]\n    public void ShouldResolveMediator()\n    {\n        _provider.GetService<IMediator>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveSender()\n    {\n        _provider.GetService<ISender>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolvePublisher()\n    {\n        _provider.GetService<IPublisher>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<Ping, Pong>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveVoidRequestHandler()\n    {\n        _provider.GetService<IRequestHandler<Ding>>().ShouldNotBeNull();\n    }\n\n    [Fact]\n    public void ShouldResolveNotificationHandlers()\n    {\n        _provider.GetServices<INotificationHandler<Pinged>>().Count().ShouldBe(4);\n    }\n\n    [Fact]\n    public void ShouldNotThrowWithMissingEnumerables()\n    {\n        Should.NotThrow(() => _provider.GetRequiredService<IEnumerable<IRequestExceptionAction<int, Exception>>>());\n    }\n\n    [Fact]\n    public void ShouldResolveFirstDuplicateHandler()\n    {\n        _provider.GetService<IRequestHandler<DuplicateTest, string>>().ShouldNotBeNull();\n        _provider.GetService<IRequestHandler<DuplicateTest, string>>()\n            .ShouldBeAssignableTo<DuplicateHandler1>();\n    }\n\n    [Fact]\n    public void ShouldResolveIgnoreSecondDuplicateHandler()\n    {\n        _provider.GetServices<IRequestHandler<DuplicateTest, string>>().Count().ShouldBe(1);\n    }\n\n    [Fact]\n    public void ShouldHandleKeyedServices()\n    {\n        IServiceCollection services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddSingleton(new Logger());\n        services.AddKeyedSingleton<string>(\"Foo\", \"Foo\");\n        services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining(typeof(Ping)));\n        var serviceProvider = services.BuildServiceProvider();\n\n        var mediator = serviceProvider.GetRequiredService<IMediator>();\n        \n        mediator.ShouldNotBeNull();\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/NotificationHandlerTests.cs",
    "content": "using System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\nnamespace MediatR.Tests;\n\npublic class NotificationHandlerTests\n{\n    public class Ping : INotification\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PongChildHandler : NotificationHandler<Ping>\n    {\n        private readonly TextWriter _writer;\n\n        public PongChildHandler(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        protected override void Handle(Ping notification)\n        {\n            _writer.WriteLine(notification.Message + \" Pong\");\n        }\n    }\n\n    [Fact]\n    public async Task Should_call_abstract_handle_method()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        INotificationHandler<Ping> handler = new PongChildHandler(writer);\n\n        await handler.Handle(\n            new Ping() { Message = \"Ping\" },\n            default\n        );\n\n        var result = builder.ToString();\n        result.ShouldContain(\"Ping Pong\");\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/NotificationPublisherTests.cs",
    "content": "﻿using System.Diagnostics;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.NotificationPublishers;\nusing Microsoft.Extensions.DependencyInjection;\nusing Shouldly;\nusing Xunit;\nusing Xunit.Abstractions;\n\nnamespace MediatR.Tests;\n\npublic class NotificationPublisherTests\n{\n    private readonly ITestOutputHelper _output;\n\n    public NotificationPublisherTests(ITestOutputHelper output) => _output = output;\n\n    public class Notification : INotification\n    {\n    }\n\n    public class FirstHandler : INotificationHandler<Notification>\n    {\n        public async Task Handle(Notification notification, CancellationToken cancellationToken) \n            => await Task.Delay(500, cancellationToken);\n    }\n    public class SecondHandler : INotificationHandler<Notification>\n    {\n        public async Task Handle(Notification notification, CancellationToken cancellationToken) \n            => await Task.Delay(250, cancellationToken);\n    }\n\n    [Fact]\n    public async Task Should_handle_sequentially_by_default()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining<Notification>();\n        });\n        var serviceProvider = services.BuildServiceProvider();\n\n        var mediator = serviceProvider.GetRequiredService<IMediator>();\n\n        var timer = new Stopwatch();\n        timer.Start();\n\n        await mediator.Publish(new Notification());\n\n        timer.Stop();\n        \n        var sequentialElapsed = timer.ElapsedMilliseconds;\n\n        services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(cfg =>\n        {\n            cfg.RegisterServicesFromAssemblyContaining<Notification>();\n            cfg.NotificationPublisherType = typeof(TaskWhenAllPublisher);\n        });\n        serviceProvider = services.BuildServiceProvider();\n\n        mediator = serviceProvider.GetRequiredService<IMediator>();\n\n        timer.Restart();\n\n        await mediator.Publish(new Notification());\n\n        timer.Stop();\n        \n        var parallelElapsed = timer.ElapsedMilliseconds;\n\n        sequentialElapsed.ShouldBeGreaterThan(parallelElapsed);\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/Pipeline/RequestExceptionActionTests.cs",
    "content": "using MediatR.Pipeline;\n\nnamespace MediatR.Tests.Pipeline;\n\npublic class RequestExceptionActionTests\n{\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public abstract class PingPongException : Exception\n    {\n        protected PingPongException(string? message) : base(message + \" Thrown\")\n        {\n        }\n    }\n\n    public class PingException : PingPongException\n    {\n        public PingException(string? message) : base(message)\n        {\n        }\n    }\n\n    public class PongException : PingPongException\n    {\n        public PongException(string message) : base(message)\n        {\n        }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            throw new PingException(request.Message);\n        }\n    }\n\n    public class GenericExceptionAction<TRequest> : IRequestExceptionAction<TRequest, Exception> where TRequest : notnull\n    {\n        public int ExecutionCount { get; private set; }\n\n        public Task Execute(TRequest request, Exception exception, CancellationToken cancellationToken)\n        {\n            ExecutionCount++;\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionAction<TRequest> : IRequestExceptionAction<TRequest, PingPongException> where TRequest : notnull\n    {\n        public bool Executed { get; private set; }\n\n        public Task Execute(TRequest request, PingPongException exception, CancellationToken cancellationToken)\n        {\n            Executed = true;\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingExceptionAction : IRequestExceptionAction<Ping, PingException>\n    {\n        public bool Executed { get; private set; }\n\n        public Task Execute(Ping request, PingException exception, CancellationToken cancellationToken)\n        {\n            Executed = true;\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PongExceptionAction : IRequestExceptionAction<Ping, PongException>\n    {\n        public bool Executed { get; private set; }\n\n        public Task Execute(Ping request, PongException exception, CancellationToken cancellationToken)\n        {\n            Executed = true;\n            return Task.CompletedTask;\n        }\n    }\n\n    [Fact]\n    public async Task Should_run_all_exception_actions_that_match_base_type()\n    {\n        var pingExceptionAction = new PingExceptionAction();\n        var pongExceptionAction = new PongExceptionAction();\n        var pingPongExceptionAction = new PingPongExceptionAction<Ping>();\n        \n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddTransient<IRequestExceptionAction<Ping, PingException>>(_ => pingExceptionAction);\n            cfg.AddTransient<IRequestExceptionAction<Ping, PingPongException>>(_ => pingPongExceptionAction);\n            cfg.AddTransient<IRequestExceptionAction<Ping, PongException>>(_ => pongExceptionAction);\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionActionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var request = new Ping { Message = \"Ping!\" };\n        await Assert.ThrowsAsync<PingException>(() => mediator.Send(request));\n\n        pingExceptionAction.Executed.ShouldBeTrue();\n        pingPongExceptionAction.Executed.ShouldBeTrue();\n        pongExceptionAction.Executed.ShouldBeFalse();\n    }\n\n    [Fact]\n    public async Task Should_run_matching_exception_actions_only_once()\n    {\n        var genericExceptionAction = new GenericExceptionAction<Ping>();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddTransient<IRequestExceptionAction<Ping, Exception>>(_ => genericExceptionAction);\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionActionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var request = new Ping { Message = \"Ping!\" };\n        await Assert.ThrowsAsync<PingException>(() => mediator.Send(request));\n\n        genericExceptionAction.ExecutionCount.ShouldBe(1);\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/Pipeline/RequestExceptionHandlerTests.cs",
    "content": "namespace MediatR.Tests.Pipeline;\n\nusing System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class RequestExceptionHandlerTests\n{\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingException : Exception\n    {\n        public PingException(string? message) : base(message + \" Thrown\")\n        {\n        }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            throw new PingException(request.Message);\n        }\n    }\n\n    public class GenericPingExceptionHandler : IRequestExceptionHandler<Ping, Pong, Exception>\n    {\n        public int ExecutionCount { get; private set; }\n\n        public Task Handle(Ping request, Exception exception, RequestExceptionHandlerState<Pong> state, CancellationToken cancellationToken)\n        {\n            ExecutionCount++;\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionHandlerForType : IRequestExceptionHandler<Ping, Pong, PingException>\n    {\n        public Task Handle(Ping request, PingException exception, RequestExceptionHandlerState<Pong> state, CancellationToken cancellationToken)\n        {\n            state.SetHandled(new Pong() { Message = exception.Message + \" Handled by Type\" });\n\n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionHandler : IRequestExceptionHandler<Ping, Pong, Exception>\n    {\n        public Task Handle(Ping request, Exception exception, RequestExceptionHandlerState<Pong> state, CancellationToken token)\n        {\n            state.SetHandled(new Pong() { Message = exception.Message + \" Handled\"});\n            \n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongExceptionHandlerNotHandled : IRequestExceptionHandler<Ping, Pong, Exception>\n    {\n        public Task Handle(Ping request, Exception exception, RequestExceptionHandlerState<Pong> state, CancellationToken token)\n        {\n            request.Message = exception.Message + \" Not Handled\";\n            \n            return Task.CompletedTask;\n        }\n    }\n\n    public class PingPongThrowingExceptionHandler : IRequestExceptionHandler<Ping, Pong, Exception>\n    {\n        public Task Handle(Ping request, Exception exception, RequestExceptionHandlerState<Pong> state, CancellationToken token)\n        {\n            throw new ApplicationException(\"Surprise!\");\n        }\n    }\n\n    [Fact]\n    public async Task Should_run_exception_handler_and_allow_for_exception_not_to_throw()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddTransient<IRequestExceptionHandler<Ping, Pong, Exception>, PingPongExceptionHandler>();\n            cfg.AddTransient<IRequestExceptionHandler<Ping, Pong, PingException>, PingPongExceptionHandlerForType>();\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Thrown Handled by Type\");\n    }\n\n    [Fact]\n    public async Task Should_run_exception_handler_and_allow_for_exception_to_be_still_thrown()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddTransient<IRequestExceptionHandler<Ping, Pong, Exception>, PingPongExceptionHandlerNotHandled>();\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var request = new Ping { Message = \"Ping\" };\n        await Should.ThrowAsync<PingException>(async () =>\n        {\n            await mediator.Send(request);\n        });\n\n        request.Message.ShouldBe(\"Ping Thrown Not Handled\");\n    }\n\n    [Fact]\n    public async Task Should_run_exception_handler_and_unwrap_expections_thrown_in_the_handler()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddTransient<IRequestExceptionHandler<Ping, Pong, Exception>, PingPongThrowingExceptionHandler>();\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var request = new Ping { Message = \"Ping\" };\n        await Should.ThrowAsync<ApplicationException>(async () =>\n        {\n            await mediator.Send(request);\n        });\n    }\n\n    [Fact]\n    public async Task Should_run_matching_exception_handlers_only_once()\n    {\n        var genericPingExceptionHandler = new GenericPingExceptionHandler();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.AddTransient<IRequestHandler<Ping, Pong>, PingHandler>();\n            cfg.AddSingleton<IRequestExceptionHandler<Ping, Pong, Exception>>(genericPingExceptionHandler);\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestExceptionProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var request = new Ping { Message = \"Ping\" };\n        await Should.ThrowAsync<PingException>(async () =>\n        {\n            await mediator.Send(request);\n        });\n\n        genericPingExceptionHandler.ExecutionCount.ShouldBe(1);\n    }\n\n}"
  },
  {
    "path": "test/MediatR.Tests/Pipeline/RequestPostProcessorTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests.Pipeline;\n\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class RequestPostProcessorTests\n{\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\n        }\n    }\n\n    public class PingPongPostProcessor : IRequestPostProcessor<Ping, Pong>\n    {\n        public Task Process(Ping request, Pong response, CancellationToken cancellationToken)\n        {\n            response.Message = response.Message + \" \" + request.Message;\n\n            return Task.FromResult(0);\n        }\n    }\n\n    [Fact]\n    public async Task Should_run_postprocessors()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>()).AsImplementedInterfaces();\n            });\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong Ping\");\n    }\n\n}"
  },
  {
    "path": "test/MediatR.Tests/Pipeline/RequestPreProcessorTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests.Pipeline;\n\nusing System.Threading.Tasks;\nusing MediatR.Pipeline;\nusing Shouldly;\nusing Xunit;\n\npublic class RequestPreProcessorTests\n{\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            return Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\n        }\n    }\n\n    public class PingPreProcessor : IRequestPreProcessor<Ping>\n    {\n        public Task Process(Ping request, CancellationToken cancellationToken)\n        {\n            request.Message = request.Message + \" Ping\";\n\n            return Task.FromResult(0);\n        }\n    }\n\n    [Fact]\n    public async Task Should_run_preprocessors()\n    {\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>()).AsImplementedInterfaces();\n            });\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Ping Pong\");\n    }\n\n}"
  },
  {
    "path": "test/MediatR.Tests/Pipeline/Streams/StreamPipelineBehaviorTests.cs",
    "content": "using System.Threading;\nusing MediatR.Registration;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace MediatR.Tests.Pipeline.Streams;\n\nusing Shouldly;\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Threading.Tasks;\nusing Xunit;\n\npublic class StreamPipelineBehaviorTests\n{\n    public class Sing : IStreamRequest<Song>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Song\n    {\n        public string? Message { get; set; }\n    }\n\n    public class SingHandler : IStreamRequestHandler<Sing, Song>\n    {\n        public async IAsyncEnumerable<Song> Handle(Sing request, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            yield return await Task.Run(() => new Song { Message = request.Message + \" Song\" });\n            yield return await Task.Run(() => new Song { Message = request.Message + \" Sang\" });\n            yield return await Task.Run(() => new Song { Message = request.Message + \" Seng\" });\n        }\n    }\n\n    public class SingSongPipelineBehavior : IStreamPipelineBehavior<Sing, Song>\n    {\n        public async IAsyncEnumerable<Song> Handle(Sing request, StreamHandlerDelegate<Song> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            yield return new Song { Message = \"Start behaving...\" };\n\n            await foreach (var item in next().WithCancellation(cancellationToken).ConfigureAwait(false))\n            {\n                yield return item;\n            }\n\n            yield return new Song { Message = \"...Ready behaving\" };\n        }\n    }\n\n    [Fact]\n    public async Task Should_run_pipeline_behavior()\n    {\n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddMediatR(opts =>\n        {\n            opts.RegisterServicesFromAssemblyContaining<PublishTests>();\n            opts.AddStreamBehavior<SingSongPipelineBehavior>();\n        });\n        \n        var container = services.BuildServiceProvider();\n        \n        var mediator = container.GetRequiredService<IMediator>();\n\n        var responses = mediator.CreateStream(new Sing { Message = \"Sing\" });\n\n        int i = 0;\n        await foreach (var response in responses)\n        {\n            if (i == 0)\n            {\n                response.Message.ShouldBe(\"Start behaving...\");\n            }\n            else if (i == 1)\n            {\n                response.Message.ShouldBe(\"Sing Song\");\n            }\n            else if (i == 2)\n            {\n                response.Message.ShouldBe(\"Sing Sang\");\n            }\n            else if (i == 3)\n            {\n                response.Message.ShouldBe(\"Sing Seng\");\n            }\n            else if (i == 4)\n            {\n                response.Message.ShouldBe(\"...Ready behaving\");\n            }\n\n            (++i).ShouldBeLessThanOrEqualTo(5);\n        }\n    }\n\n}"
  },
  {
    "path": "test/MediatR.Tests/PipelineTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class PipelineTests\n{\n    public class Ping : IRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class VoidPing : IRequest\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Zing : IRequest<Zong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Zong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public PingHandler(Logger output)\n        {\n            _output = output;\n        }\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            return Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\n        }\n    }\n\n    public class VoidPingHandler : IRequestHandler<VoidPing>\n    {\n        private readonly Logger _output;\n\n        public VoidPingHandler(Logger output)\n        {\n            _output = output;\n        }\n        public Task Handle(VoidPing request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            return Task.CompletedTask;\n        }\n    }\n\n    public class ZingHandler : IRequestHandler<Zing, Zong>\n    {\n        private readonly Logger _output;\n\n        public ZingHandler(Logger output)\n        {\n            _output = output;\n        }\n        public Task<Zong> Handle(Zing request, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            return Task.FromResult(new Zong { Message = request.Message + \" Zong\" });\n        }\n    }\n\n    public class OuterBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            var response = await next();\n            _output.Messages.Add(\"Outer after\");\n\n            return response;\n        }\n    }\n\n    public class OuterVoidBehavior : IPipelineBehavior<VoidPing, Unit>\n    {\n        private readonly Logger _output;\n\n        public OuterVoidBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Unit> Handle(VoidPing request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            var response = await next();\n            _output.Messages.Add(\"Outer after\");\n\n            return response;\n        }\n    }\n\n    public class InnerBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            var response = await next();\n            _output.Messages.Add(\"Inner after\");\n\n            return response;\n        }\n    }\n\n    public class InnerVoidBehavior : IPipelineBehavior<VoidPing, Unit>\n    {\n        private readonly Logger _output;\n\n        public InnerVoidBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Unit> Handle(VoidPing request, RequestHandlerDelegate<Unit> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            var response = await next();\n            _output.Messages.Add(\"Inner after\");\n\n            return response;\n        }\n    }\n\n    public class InnerBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> \n        where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner generic before\");\n            var response = await next();\n            _output.Messages.Add(\"Inner generic after\");\n\n            return response;\n        }\n    }\n\n    public class OuterBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer generic before\");\n            var response = await next();\n            _output.Messages.Add(\"Outer generic after\");\n\n            return response;\n        }\n    }\n\n    public class ConstrainedBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\n        where TRequest : Ping\n        where TResponse : Pong\n    {\n        private readonly Logger _output;\n\n        public ConstrainedBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Constrained before\");\n            var response = await next();\n            _output.Messages.Add(\"Constrained after\");\n\n            return response;\n        }\n    }\n\n    public class ConcreteBehavior : IPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public ConcreteBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async Task<Pong> Handle(Ping request, RequestHandlerDelegate<Pong> next, CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Concrete before\");\n            var response = await next();\n            _output.Messages.Add(\"Concrete after\");\n\n            return response;\n        }\n    }\n\n    public class Logger\n    {\n        public IList<string> Messages { get; } = new List<string>();\n    }\n\n    [Fact]\n    public async Task Should_wrap_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n            cfg.AddTransient<IPipelineBehavior<Ping, Pong>, OuterBehavior>();\n            cfg.AddTransient<IPipelineBehavior<Ping, Pong>, InnerBehavior>();\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new []\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n\n    [Fact]\n    public async Task Should_wrap_void_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n            cfg.AddTransient<IPipelineBehavior<VoidPing, Unit>, OuterVoidBehavior>();\n            cfg.AddTransient<IPipelineBehavior<VoidPing, Unit>, InnerVoidBehavior>();\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Send(new VoidPing { Message = \"Ping\" });\n\n        output.Messages.ShouldBe(new []\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n\n    [Fact]\n    public async Task Should_wrap_generics_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(InnerBehavior<,>));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact]\n    public async Task Should_wrap_void_generics_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(InnerBehavior<,>));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Send(new VoidPing { Message = \"Ping\" });\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact]\n    public async Task Should_handle_constrained_generics()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(InnerBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(ConstrainedBehavior<,>));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        //container.GetAllInstances<IPipelineBehavior<Ping, Pong>>();\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Constrained before\",\n            \"Handler\",\n            \"Constrained after\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n\n        output.Messages.Clear();\n\n        var zingResponse = await mediator.Send(new Zing { Message = \"Zing\" });\n\n        zingResponse.Message.ShouldBe(\"Zing Zong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact(Skip = \"Lamar does not mix concrete and open generics. Use constraints instead.\")]\n    public async Task Should_handle_concrete_and_open_generics()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>()).AsImplementedInterfaces()\n                    .AddClasses(t => t.AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<,>), typeof(InnerBehavior<,>));\n            cfg.AddTransient(typeof(IPipelineBehavior<Ping, Pong>), typeof(ConcreteBehavior));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        //container.GetAllInstances<IPipelineBehavior<Ping, Pong>>();\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        var response = await mediator.Send(new Ping { Message = \"Ping\" });\n\n        response.Message.ShouldBe(\"Ping Pong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Concrete before\",\n            \"Handler\",\n            \"Concrete after\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n\n        output.Messages.Clear();\n\n        var zingResponse = await mediator.Send(new Zing { Message = \"Zing\" });\n\n        zingResponse.Message.ShouldBe(\"Zing Zong\");\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/PublishTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class PublishTests\n{\n    public class Ping : INotification\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PongHandler : INotificationHandler<Ping>\n    {\n        private readonly TextWriter _writer;\n\n        public PongHandler(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        public Task Handle(Ping notification, CancellationToken cancellationToken)\n        {\n            return _writer.WriteLineAsync(notification.Message + \" Pong\");\n        }\n    }\n\n    public class PungHandler : INotificationHandler<Ping>\n    {\n        private readonly TextWriter _writer;\n\n        public PungHandler(TextWriter writer)\n        {\n            _writer = writer;\n        }\n\n        public Task Handle(Ping notification, CancellationToken cancellationToken)\n        {\n            return _writer.WriteLineAsync(notification.Message + \" Pung\");\n        }\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Publish(new Ping { Message = \"Ping\" });\n\n        var result = builder.ToString().Split(new [] {Environment.NewLine}, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler_when_object_is_passed()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        object message = new Ping { Message = \"Ping\" };\n        await mediator.Publish(message);\n\n        var result = builder.ToString().Split(new [] {Environment.NewLine}, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n    }\n\n    public class SequentialMediator : Mediator\n    {\n        public SequentialMediator(IServiceProvider serviceProvider)\n            : base(serviceProvider)\n        {\n        }\n\n        protected override async Task PublishCore(IEnumerable<NotificationHandlerExecutor> allHandlers, INotification notification, CancellationToken cancellationToken)\n        {\n            foreach (var handler in allHandlers)\n            {\n                await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);\n            }\n        }\n    }\n\n    public class SequentialPublisher : INotificationPublisher\n    {\n        public int CallCount { get; set; }\n\n        public async Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)\n        {\n            foreach (var handler in handlerExecutors)\n            {\n                await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);\n                CallCount++;\n            }\n        }\n    }\n\n    [Fact]\n    public async Task Should_override_with_sequential_firing()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IMediator, SequentialMediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Publish(new Ping { Message = \"Ping\" });\n\n        var result = builder.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n    }\n\n    [Fact]\n    public async Task Should_override_with_sequential_firing_through_injection()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n        var publisher = new SequentialPublisher();\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddSingleton<INotificationPublisher>(publisher);\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Publish(new Ping { Message = \"Ping\" });\n\n        var result = builder.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n        publisher.CallCount.ShouldBe(2);\n    }\n\n    [Fact]\n    public async Task Should_resolve_handlers_given_interface()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IMediator, SequentialMediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        // wrap notifications in an array, so this test won't break on a 'replace with var' refactoring\n        var notifications = new INotification[] { new Ping { Message = \"Ping\" } };\n        await mediator.Publish(notifications[0]);\n\n        var result = builder.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_handler_by_specific_interface()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(INotificationHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IPublisher, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IPublisher>();\n\n        await mediator.Publish(new Ping { Message = \"Ping\" });\n\n        var result = builder.ToString().Split(new [] {Environment.NewLine}, StringSplitOptions.None);\n        result.ShouldContain(\"Ping Pong\");\n        result.ShouldContain(\"Ping Pung\");\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/SendTests.cs",
    "content": "using System.Threading;\r\n\r\nusing System;\r\nusing System.Threading.Tasks;\r\nusing Shouldly;\r\nusing Xunit;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing System.Reflection;\r\nusing MediatR.Pipeline;\r\n\r\nnamespace MediatR.Tests;\r\npublic class SendTests\r\n{\r\n    private readonly IServiceProvider _serviceProvider;\r\n    private Dependency _dependency;\r\n    private readonly IMediator _mediator;\r\n\r\n    public SendTests()\r\n    {\r\n        _dependency = new Dependency();\r\n        var services = new ServiceCollection();\r\n        services.AddFakeLogging();\r\n        services.AddMediatR(cfg =>\r\n        {\r\n            cfg.RegisterServicesFromAssemblies(typeof(Ping).Assembly);\r\n            cfg.AddOpenBehavior(typeof(TimeoutBehavior<,>), ServiceLifetime.Transient);\r\n            cfg.RegisterGenericHandlers = true;\r\n        });\r\n        services.AddSingleton(_dependency);\r\n        _serviceProvider = services.BuildServiceProvider();\r\n        _mediator = _serviceProvider.GetService<IMediator>()!;\r\n    }\r\n\r\n    public class Ping : IRequest<Pong>\r\n    {\r\n        public string? Message { get; set; }\r\n    }\r\n\r\n    public class VoidPing : IRequest\r\n    {\r\n    }\r\n\r\n    public class Pong\r\n    {\r\n        public string? Message { get; set; }\r\n    }\r\n\r\n    public class PingHandler : IRequestHandler<Ping, Pong>\r\n    {\r\n        public Task<Pong> Handle(Ping request, CancellationToken cancellationToken)\r\n        {\r\n            return Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\r\n        }\r\n    }\r\n\r\n    public class Dependency\r\n    {\r\n        public bool Called { get; set; }\r\n        public bool CalledSpecific { get; set; }\r\n    }\r\n\r\n    public class VoidPingHandler : IRequestHandler<VoidPing>\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public VoidPingHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public Task Handle(VoidPing request, CancellationToken cancellationToken)\r\n        {\r\n            _dependency.Called = true;\r\n\r\n            return Task.CompletedTask;\r\n        }\r\n    }\r\n\r\n    public class GenericPing<T> : IRequest<T>\r\n        where T : Pong\r\n    {\r\n        public T? Pong { get; set; }\r\n    }\r\n\r\n    public class GenericPingHandler<T> : IRequestHandler<GenericPing<T>, T>\r\n        where T : Pong\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public GenericPingHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public Task<T> Handle(GenericPing<T> request, CancellationToken cancellationToken)\r\n        {\r\n            _dependency.Called = true;\r\n            request.Pong!.Message += \" Pong\";\r\n            return Task.FromResult(request.Pong!);\r\n        }\r\n    }\r\n\r\n    public class VoidGenericPing<T> : IRequest\r\n        where T : Pong\r\n    { }\r\n\r\n    public class VoidGenericPingHandler<T> : IRequestHandler<VoidGenericPing<T>>\r\n        where T : Pong\r\n    {\r\n        private readonly Dependency _dependency;\r\n        public VoidGenericPingHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public Task Handle(VoidGenericPing<T> request, CancellationToken cancellationToken)\r\n        {\r\n            _dependency.Called = true;\r\n\r\n            return Task.CompletedTask;\r\n        }\r\n    }\r\n\r\n    public class PongExtension : Pong\r\n    {\r\n\r\n    }\r\n\r\n    public class TestClass1PingRequestHandler : IRequestHandler<VoidGenericPing<PongExtension>>\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public TestClass1PingRequestHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public Task Handle(VoidGenericPing<PongExtension> request, CancellationToken cancellationToken)\r\n        {\r\n            _dependency.CalledSpecific = true;\r\n            return Task.CompletedTask;\r\n        }\r\n    }\r\n\r\n    public interface ITestInterface1 { }\r\n    public interface ITestInterface2 { }\r\n    public interface ITestInterface3 { }\r\n\r\n    public class TestClass1 : ITestInterface1 { }\r\n    public class TestClass2 : ITestInterface2 { }\r\n    public class TestClass3 : ITestInterface3 { }\r\n\r\n    public class MultipleGenericTypeParameterRequest<T1, T2, T3> : IRequest<int>\r\n       where T1 : ITestInterface1\r\n       where T2 : ITestInterface2\r\n       where T3 : ITestInterface3\r\n    {\r\n        public int Foo { get; set; }\r\n    }\r\n\r\n    public class MultipleGenericTypeParameterRequestHandler<T1, T2, T3> : IRequestHandler<MultipleGenericTypeParameterRequest<T1, T2, T3>, int>\r\n        where T1 : ITestInterface1\r\n        where T2 : ITestInterface2\r\n        where T3 : ITestInterface3\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public MultipleGenericTypeParameterRequestHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public Task<int> Handle(MultipleGenericTypeParameterRequest<T1, T2, T3> request, CancellationToken cancellationToken)\r\n        {\r\n            _dependency.Called = true;\r\n            return Task.FromResult(1);\r\n        }\r\n    }\r\n\r\n    public class TimeoutBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>\r\n        where TRequest : notnull\r\n    {\r\n        public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)\r\n        {\r\n            using (var cts = new CancellationTokenSource(500))\r\n            {\r\n                return await next(cts.Token);\r\n            }\r\n        }\r\n    }\r\n\r\n    public class TimeoutRequest : IRequest\r\n    {\r\n    }\r\n\r\n    public class TimeoutRequest2 : IRequest<int>\r\n    {\r\n    }\r\n\r\n    public class TimeoutRequestHandler : IRequestHandler<TimeoutRequest>\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public TimeoutRequestHandler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public async Task Handle(TimeoutRequest request, CancellationToken cancellationToken)\r\n        {\r\n            await Task.Delay(2000, cancellationToken);\r\n\r\n            _dependency.Called = true;\r\n        }\r\n    }\r\n\r\n    public class TimeoutRequest2Handler : IRequestHandler<TimeoutRequest2, int>\r\n    {\r\n        private readonly Dependency _dependency;\r\n\r\n        public TimeoutRequest2Handler(Dependency dependency) => _dependency = dependency;\r\n\r\n        public async Task<int> Handle(TimeoutRequest2 request, CancellationToken cancellationToken)\r\n        {\r\n            await Task.Delay(2000, cancellationToken);\r\n\r\n            _dependency.Called = true;\r\n            return 1;\r\n        }\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_handler()\r\n    {\r\n        var response = await _mediator.Send(new Ping { Message = \"Ping\" });\r\n\r\n        response.Message.ShouldBe(\"Ping Pong\");\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_void_handler()\r\n    {\r\n        await _mediator.Send(new VoidPing());\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_handler_via_dynamic_dispatch()\r\n    {\r\n        object request = new Ping { Message = \"Ping\" };\r\n        var response = await _mediator.Send(request);\r\n\r\n        var pong = response.ShouldBeOfType<Pong>();\r\n        pong.Message.ShouldBe(\"Ping Pong\");\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_void_handler_via_dynamic_dispatch()\r\n    {\r\n        object request = new VoidPing();\r\n        var response = await _mediator.Send(request);\r\n\r\n        response.ShouldBeOfType<Unit>();\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_handler_by_specific_interface()\r\n    {\r\n        var response = await _mediator.Send(new Ping { Message = \"Ping\" });\r\n\r\n        response.Message.ShouldBe(\"Ping Pong\");\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_main_handler_by_given_interface()\r\n    {\r\n        // wrap requests in an array, so this test won't break on a 'replace with var' refactoring\r\n        var requests = new IRequest[] { new VoidPing() };\r\n        await _mediator.Send(requests[0]);\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public Task Should_raise_execption_on_null_request() => Should.ThrowAsync<ArgumentNullException>(async () => await _mediator.Send(default!));\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_generic_handler()\r\n    {\r\n        var request = new GenericPing<Pong> { Pong = new Pong { Message = \"Ping\" } };\r\n        var result = await _mediator.Send(request);\r\n\r\n        var pong = result.ShouldBeOfType<Pong>();\r\n        pong.Message.ShouldBe(\"Ping Pong\");\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_generic_void_handler()\r\n    {\r\n        var request = new VoidGenericPing<Pong>();\r\n        await _mediator.Send(request);\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_multiple_type_parameter_generic_handler()\r\n    {\r\n        var request = new MultipleGenericTypeParameterRequest<TestClass1, TestClass2, TestClass3>();\r\n        await _mediator.Send(request);\r\n\r\n        _dependency.Called.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_closed_handler_if_defined()\r\n    {\r\n        var dependency = new Dependency();\r\n        var services = new ServiceCollection();\r\n        services.AddSingleton(dependency);\r\n        services.AddFakeLogging();\r\n        services.AddMediatR(cfg =>\r\n        {\r\n            cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());\r\n            cfg.RegisterGenericHandlers = true;\r\n        });\r\n\r\n        services.AddTransient<IRequestHandler<VoidGenericPing<PongExtension>>,TestClass1PingRequestHandler>();\r\n        var serviceProvider = services.BuildServiceProvider();\r\n        var mediator = serviceProvider.GetService<IMediator>()!;\r\n\r\n        var request = new VoidGenericPing<PongExtension>();\r\n        await mediator.Send(request);\r\n\r\n        dependency.Called.ShouldBeFalse();\r\n        dependency.CalledSpecific.ShouldBeTrue();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task Should_resolve_open_handler_if_not_defined()\r\n    {\r\n        var dependency = new Dependency();\r\n        var services = new ServiceCollection();\r\n        services.AddFakeLogging();\r\n        services.AddSingleton(dependency);\r\n        services.AddMediatR(cfg => \r\n        {\r\n            cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());\r\n            cfg.RegisterGenericHandlers = true;\r\n        });\r\n        services.AddTransient<IRequestHandler<VoidGenericPing<PongExtension>>, TestClass1PingRequestHandler>();\r\n        var serviceProvider = services.BuildServiceProvider();\r\n        var mediator = serviceProvider.GetService<IMediator>()!;\r\n\r\n        var request = new VoidGenericPing<Pong>();\r\n        await mediator.Send(request);\r\n\r\n        dependency.Called.ShouldBeTrue();\r\n        dependency.CalledSpecific.ShouldBeFalse();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task TimeoutBehavior_Void_Should_Cancel_Long_Running_Task_And_Throw_Exception()\r\n    {\r\n        var request = new TimeoutRequest();\r\n\r\n        var exception = await Should.ThrowAsync<TaskCanceledException>(() => _mediator.Send(request));\r\n\r\n        exception.ShouldNotBeNull();\r\n        exception.ShouldBeAssignableTo<TaskCanceledException>();\r\n        _dependency.Called.ShouldBeFalse();\r\n    }\r\n\r\n    [Fact]\r\n    public async Task TimeoutBehavior_NonVoid_Should_Cancel_Long_Running_Task_And_Throw_Exception()\r\n    {\r\n        var request = new TimeoutRequest2();\r\n        int result = 0;\r\n\r\n        var exception = await Should.ThrowAsync<TaskCanceledException>(async () => { result = await _mediator.Send(request); });\r\n\r\n        exception.ShouldNotBeNull();\r\n        exception.ShouldBeAssignableTo<TaskCanceledException>();\r\n        _dependency.Called.ShouldBeFalse();\r\n        result.ShouldBe(0);\r\n    }\r\n}"
  },
  {
    "path": "test/MediatR.Tests/SendVoidInterfaceTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System.IO;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class SendVoidInterfaceTests\n{\n    public class Ping : IRequest\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IRequestHandler<Ping>\n    {\n        private readonly TextWriter _writer;\n\n        public PingHandler(TextWriter writer) => _writer = writer;\n\n        public Task Handle(Ping request, CancellationToken cancellationToken)\n            => _writer.WriteAsync(request.Message + \" Pong\");\n    }\n\n    [Fact]\n    public async Task Should_resolve_main_void_handler()\n    {\n        var builder = new StringBuilder();\n        var writer = new StringWriter(builder);\n\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<,>))).AsImplementedInterfaces()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IRequestHandler<>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<TextWriter>(writer);\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await mediator.Send(new Ping { Message = \"Ping\" });\n\n        builder.ToString().ShouldBe(\"Ping Pong\");\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/ServiceFactoryTests.cs",
    "content": "using System;\nusing System.Collections;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing MediatR.Licensing;\nusing MediatR.Registration;\nusing Microsoft.Extensions.DependencyInjection;\nusing Xunit;\n\nnamespace MediatR.Tests;\n\n[CollectionDefinition(nameof(ServiceFactoryCollectionBehavior), DisableParallelization = true)]\npublic class ServiceFactoryCollectionBehavior {}\n\n[Collection(nameof(ServiceFactoryCollectionBehavior))]\npublic class ServiceFactoryTests\n{\n    public class Ping : IRequest<Pong>\n    {\n\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    [Fact]\n    public async Task Should_throw_given_no_handler()\n    {\n        MediatRServiceCollectionExtensions.LicenseChecked = false;\n      \n        var serviceCollection = new ServiceCollection();\n        ServiceRegistrar.AddRequiredServices(serviceCollection, new MediatRServiceConfiguration());\n        serviceCollection.AddFakeLogging();\n        var serviceProvider = serviceCollection.BuildServiceProvider();\n\n        \n        var mediator = new Mediator(serviceProvider);\n\n        await Assert.ThrowsAsync<InvalidOperationException>(\n            () => mediator.Send(new Ping())\n        );\n    }\n\n    [Fact]\n    public void Should_not_throw_with_manual_registration()\n    {\n        MediatRServiceCollectionExtensions.LicenseChecked = false;\n      \n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddTransient<IMediator, Mediator>();\n        var config = new MediatRServiceConfiguration();\n        services.AddSingleton(config);\n        services.AddSingleton<LicenseAccessor>();\n        services.AddSingleton<LicenseValidator>();\n\n        var container = services.BuildServiceProvider();\n\n        Should.NotThrow(() => container.GetRequiredService<IMediator>());\n    }\n    \n    [Fact]\n    public void Should_throw_when_missing_required_configuration()\n    {\n        MediatRServiceCollectionExtensions.LicenseChecked = false;\n        \n        var services = new ServiceCollection();\n        services.AddFakeLogging();\n        services.AddTransient<IMediator, Mediator>();\n\n        var container = services.BuildServiceProvider();\n\n        Should.Throw<InvalidOperationException>(() => container.GetRequiredService<IMediator>());\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/StreamPipelineTests.cs",
    "content": "using System.Threading;\n\nnamespace MediatR.Tests;\n\nusing System.Collections.Generic;\nusing System.Runtime.CompilerServices;\nusing System.Threading.Tasks;\nusing Shouldly;\nusing Xunit;\n\npublic class StreamPipelineTests\n{\n    public class Ping : IStreamRequest<Pong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Pong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Zing : IStreamRequest<Zong>\n    {\n        public string? Message { get; set; }\n    }\n\n    public class Zong\n    {\n        public string? Message { get; set; }\n    }\n\n    public class PingHandler : IStreamRequestHandler<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public PingHandler(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, [EnumeratorCancellation]CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            yield return await Task.FromResult(new Pong { Message = request.Message + \" Pong\" });\n        }\n    }\n\n    public class ZingHandler : IStreamRequestHandler<Zing, Zong>\n    {\n        private readonly Logger _output;\n\n        public ZingHandler(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Zong> Handle(Zing request, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Handler\");\n            yield return await Task.FromResult(new Zong { Message = request.Message + \" Zong\" });\n        }\n    }\n\n    public class OuterBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Outer after\");\n        }\n    }\n\n    public class InnerBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Inner after\");\n        }\n    }\n\n    public class InnerBehavior<TRequest, TResponse> : IStreamPipelineBehavior<TRequest, TResponse>\n        where TRequest : IStreamRequest<TResponse>\n    {\n        private readonly Logger _output;\n\n        public InnerBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Inner generic before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Inner generic after\");\n        }\n    }\n\n    public class OuterBehavior<TRequest, TResponse> : IStreamPipelineBehavior<TRequest, TResponse>\n        where TRequest : IStreamRequest<TResponse>\n    {\n        private readonly Logger _output;\n\n        public OuterBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Outer generic before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Outer generic after\");\n        }\n    }\n\n    public class ConstrainedBehavior<TRequest, TResponse> : IStreamPipelineBehavior<TRequest, TResponse>\n        where TRequest : Ping, IStreamRequest<TResponse>\n        where TResponse : Pong\n    {\n        private readonly Logger _output;\n\n        public ConstrainedBehavior(Logger output)\n        {\n            _output = output;\n        }\n        public async IAsyncEnumerable<TResponse> Handle(TRequest request, StreamHandlerDelegate<TResponse> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Constrained before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Constrained after\");\n        }\n    }\n\n    public class ConcreteBehavior : IStreamPipelineBehavior<Ping, Pong>\n    {\n        private readonly Logger _output;\n\n        public ConcreteBehavior(Logger output)\n        {\n            _output = output;\n        }\n\n        public async IAsyncEnumerable<Pong> Handle(Ping request, StreamHandlerDelegate<Pong> next, [EnumeratorCancellation] CancellationToken cancellationToken)\n        {\n            _output.Messages.Add(\"Concrete before\");\n            await foreach (var result in next())\n            {\n                yield return result;\n            }\n            _output.Messages.Add(\"Concrete after\");\n        }\n    }\n\n    public class Logger\n    {\n        public IList<string> Messages { get; } = new List<string>();\n    }\n\n    [Fact]\n    public async Task Should_wrap_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n            cfg.AddTransient<IStreamPipelineBehavior<Ping, Pong>, OuterBehavior>();\n            cfg.AddTransient<IStreamPipelineBehavior<Ping, Pong>, InnerBehavior>();\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await foreach(var response in mediator.CreateStream(new Ping { Message = \"Ping\" }))\n        {\n            response.Message.ShouldBe(\"Ping Pong\");\n        }\n\n        output.Messages.ShouldBe(new []\n        {\n            \"Outer before\",\n            \"Inner before\",\n            \"Handler\",\n            \"Inner after\",\n            \"Outer after\"\n        });\n    }\n\n    [Fact]\n    public async Task Should_wrap_generics_with_behavior()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(InnerBehavior<,>));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await foreach (var response in mediator.CreateStream(new Ping { Message = \"Ping\" }))\n        {\n            response.Message.ShouldBe(\"Ping Pong\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact]\n    public async Task Should_handle_constrained_generics()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>().AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(InnerBehavior<,>));\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(ConstrainedBehavior<,>));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await foreach (var response in mediator.CreateStream(new Ping { Message = \"Ping\" }))\n        {\n            response.Message.ShouldBe(\"Ping Pong\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Constrained before\",\n            \"Handler\",\n            \"Constrained after\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n\n        output.Messages.Clear();\n\n        await foreach (var response in mediator.CreateStream(new Zing { Message = \"Zing\" }))\n        {\n            response.Message.ShouldBe(\"Zing Zong\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n\n    [Fact(Skip = \"Lamar does not mix concrete and open generics. Use constraints instead.\")]\n    public async Task Should_handle_concrete_and_open_generics()\n    {\n        var output = new Logger();\n        var container = TestContainer.Create(cfg =>\n        {\n            cfg.Scan(scanner =>\n            {\n                scanner.FromAssemblyOf<PublishTests>()\n                    .AddClasses(t => t.InNamespaceOf<Ping>()).AsImplementedInterfaces()\n                    .AddClasses(t => t.AssignableTo(typeof(IStreamRequestHandler<,>))).AsImplementedInterfaces();\n            });\n            cfg.AddSingleton<Logger>(output);\n\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(OuterBehavior<,>));\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<,>), typeof(InnerBehavior<,>));\n            cfg.AddTransient(typeof(IStreamPipelineBehavior<Ping, Pong>), typeof(ConcreteBehavior));\n\n            cfg.AddTransient<IMediator, Mediator>();\n        });\n\n        var mediator = container.GetRequiredService<IMediator>();\n\n        await foreach (var response in mediator.CreateStream(new Ping { Message = \"Ping\" }))\n        {\n            response.Message.ShouldBe(\"Ping Pong\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Concrete before\",\n            \"Handler\",\n            \"Concrete after\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n\n        output.Messages.Clear();\n\n        await foreach (var response in mediator.CreateStream(new Zing { Message = \"Zing\" }))\n        {\n            response.Message.ShouldBe(\"Zing Zong\");\n        }\n\n        output.Messages.ShouldBe(new[]\n        {\n            \"Outer generic before\",\n            \"Inner generic before\",\n            \"Handler\",\n            \"Inner generic after\",\n            \"Outer generic after\",\n        });\n    }\n}"
  },
  {
    "path": "test/MediatR.Tests/TestContainer.cs",
    "content": "using MediatR.Licensing;\nusing MediatR.Registration;\nusing Microsoft.Extensions.Logging;\nusing Microsoft.Extensions.Logging.Abstractions;\n\nnamespace MediatR.Tests;\n\npublic static class TestContainer\n{\n    public static IServiceProvider Create(Action<ServiceCollection> config)\n    {\n        var services = new ServiceCollection();\n        \n        ConfigAction(services);\n\n        var container = services.BuildServiceProvider();\n\n        return container;\n\n        void ConfigAction(ServiceCollection cfg)\n        {\n            cfg.AddSingleton<ILoggerFactory, NullLoggerFactory>();\n\n            ServiceRegistrar.AddRequiredServices(cfg, new MediatRServiceConfiguration());\n\n            config(cfg);\n        }\n    } \n}"
  },
  {
    "path": "test/MediatR.Tests/UnitTests.cs",
    "content": "using System;\nusing System.Linq;\nusing System.Collections.Generic;\nusing System.Threading.Tasks;\nusing Xunit;\n\nnamespace MediatR.Tests;\n\npublic class UnitTests\n{\n    [Fact]\n    public async Task Should_be_equal_to_each_other()\n    {\n        var unit1 = Unit.Value;\n        var unit2 = await Unit.Task;\n\n        Assert.Equal(unit1, unit2);\n        Assert.True(unit1 == unit2);\n        Assert.False(unit1 != unit2);\n    }\n\n    [Fact]\n    public void Should_be_equitable()\n    {\n        var dictionary = new Dictionary<Unit, string>\n        {\n            {new Unit(), \"value\"},\n        };\n\n        Assert.Equal(\"value\", dictionary[default]);\n    }\n\n    [Fact]\n    public void Should_tostring()\n    {\n        var unit = Unit.Value;\n        Assert.Equal(\"()\", unit.ToString());\n    }\n\n    [Fact]\n    public void Should_compareto_as_zero()\n    {\n        var unit1 = new Unit();\n        var unit2 = new Unit();\n\n        Assert.Equal(0, unit1.CompareTo(unit2));\n    }\n\n    public static object[][] ValueData()\n    {\n        return new[]\n        {\n            new object[] {new object(), false},\n            new object[] {\"\", false},\n            new object[] {\"()\", false},\n            new object[] {null!, false},\n            new object[] {new Uri(\"https://www.google.com\"), false},\n            new object[] {new Unit(), true},\n            new object[] {Unit.Value, true},\n            new object[] {Unit.Task.Result, true},\n            new object[] {default(Unit), true},\n        };\n    }\n\n    public static object[][] CompareToValueData()\n        => ValueData().Select(objects => new[] { objects[0] }).ToArray();\n\n    [Theory]\n    [MemberData(nameof(ValueData))]\n    public void Should_be_equal(object value, bool isEqual)\n    {\n        var unit1 = Unit.Value;\n\n        if (isEqual)\n            Assert.True(unit1.Equals(value));\n        else\n            Assert.False(unit1.Equals(value));\n    }\n\n    [Theory]\n    [MemberData(nameof(CompareToValueData))]\n    public void Should_compareto_value_as_zero(object value)\n    {\n        var unit1 = new Unit();\n\n        Assert.Equal(0, ((IComparable)unit1).CompareTo(value));\n    }\n}"
  }
]