[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ntrim_trailing_whitespace = true\ninsert_final_newline = false\nindent_style = space\nindent_size = 4\n\n# Microsoft .NET properties\ncsharp_new_line_before_members_in_object_initializers = false\ncsharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion\ncsharp_style_var_elsewhere = true:suggestion\ncsharp_style_var_for_built_in_types = true:suggestion\ncsharp_style_var_when_type_is_apparent = true:suggestion\ndotnet_naming_rule.unity_serialized_field_rule.import_to_resharper = True\ndotnet_naming_rule.unity_serialized_field_rule.resharper_description = Unity serialized field\ndotnet_naming_rule.unity_serialized_field_rule.resharper_guid = 5f0fdb63-c892-4d2c-9324-15c80b22a7ef\ndotnet_naming_rule.unity_serialized_field_rule.severity = warning\ndotnet_naming_rule.unity_serialized_field_rule.style = lower_camel_case_style\ndotnet_naming_rule.unity_serialized_field_rule.symbols = unity_serialized_field_symbols\ndotnet_naming_style.lower_camel_case_style.capitalization = camel_case\ndotnet_naming_symbols.unity_serialized_field_symbols.applicable_accessibilities = *\ndotnet_naming_symbols.unity_serialized_field_symbols.applicable_kinds =\ndotnet_naming_symbols.unity_serialized_field_symbols.resharper_applicable_kinds = unity_serialised_field\ndotnet_naming_symbols.unity_serialized_field_symbols.resharper_required_modifiers = instance\ndotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none\ndotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none\ndotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none\ndotnet_style_predefined_type_for_locals_parameters_members = true:suggestion\ndotnet_style_predefined_type_for_member_access = true:suggestion\ndotnet_style_qualification_for_event = false:suggestion\ndotnet_style_qualification_for_field = false:suggestion\ndotnet_style_qualification_for_method = false:suggestion\ndotnet_style_qualification_for_property = false:suggestion\ndotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion\n\n# ReSharper properties\nresharper_autodetect_indent_settings = true\nresharper_use_indent_from_vs = false\nresharper_keep_existing_arrangement = false\n\nresharper_csharp_wrap_arguments_style = chop_if_long\nresharper_csharp_wrap_before_invocation_lpar = false\nresharper_csharp_wrap_before_invocation_rpar = true\nresharper_csharp_wrap_after_invocation_lpar = true\n\nresharper_csharp_wrap_parameters_style = chop_if_long\nresharper_csharp_wrap_before_declaration_lpar = false\nresharper_csharp_wrap_before_declaration_rpar = false\nresharper_csharp_wrap_after_declaration_lpar = true\n\nresharper_csharp_braces_for_ifelse = required\n\nresharper_csharp_wrap_chained_method_calls = chop_if_long\n\n# ReSharper inspection severities\nresharper_arrange_redundant_parentheses_highlighting = hint\nresharper_arrange_this_qualifier_highlighting = hint\nresharper_arrange_type_member_modifiers_highlighting = hint\nresharper_arrange_type_modifiers_highlighting = hint\nresharper_built_in_type_reference_style_for_member_access_highlighting = hint\nresharper_built_in_type_reference_style_highlighting = hint\nresharper_redundant_base_qualifier_highlighting = warning\nresharper_suggest_var_or_type_built_in_types_highlighting = hint\nresharper_suggest_var_or_type_elsewhere_highlighting = hint\nresharper_suggest_var_or_type_simple_types_highlighting = hint\nresharper_web_config_module_not_resolved_highlighting = warning\nresharper_web_config_type_not_resolved_highlighting = warning\nresharper_web_config_wrong_module_highlighting = warning\n\ndotnet_diagnostic.CA2007.severity = none # Call ConfigureAwait()\ndotnet_diagnostic.RS2003.severity = none # Rule is no longer shipped\n\n[{*.har,*.inputactions,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,jest.config}]\nindent_style = space\nindent_size = 4\n\n[*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,fs,fsi,fsscript,fsx,hlsl,hlsli,hlslinc,master,ml,mli,nuspec,paml,razor,resw,resx,shader,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}]\nindent_style = space\nindent_size = 4\ntab_width = 4\n\n[*.{yaml,yml}]\ntab_width = 2\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug.yml",
    "content": "name: Bug Report\ndescription: File a bug report\nlabels: [\"type: bug\", \"status: triage\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill out this bug report!\n  - type: textarea\n    id: description\n    attributes:\n      label: Bug description\n      description: Explain the issue you have\n    validations:\n      required: true\n  - type: textarea\n    id: expectation\n    attributes:\n      label: Expectation\n      description: Outline what your expectation would be\n    validations:\n      required: true\n  - type: textarea\n    id: code-sample\n    attributes:\n      label: Code sample\n      description: Provide a code sample that demonstrates your issue\n      render: C#\n    validations:\n      required: true\n  - type: input\n    id: version\n    attributes:\n      label: Version\n      description: What MvvmBlazor version are you using?\n    validations:\n      required: true\n  - type: dropdown\n    id: blazor-type\n    attributes:\n      label: Are you using Blazor WASM or Blazor Server?\n      multiple: false\n      options:\n        - Blazor WASM\n        - Blazor Server\n    validations:\n      required: true\n  - type: dropdown\n    id: os\n    attributes:\n      label: What operation system are you working with?\n      multiple: false\n      options:\n        - Windows\n        - Linux\n        - macOS\n        - Other\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Security vulnerabilities\n    url: https://github.com/klemmchr\n    about: Please report security vulnerabilities via email to git+mvvmblazor@klemm.one. A link to my PGP key can be found in my profile.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature.yml",
    "content": "name: Feature request\ndescription: Propose a new feature\nlabels: [\"type: feature\", \"status: triage\"]\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Feature description\n      description: Describe the feature you would like to have\n    validations:\n      required: true\n  - type: textarea\n    id: code-sample\n    attributes:\n      label: Code sample\n      description: Provide a code sample if applicable \n      render: C#\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other.yml",
    "content": "name: Other\ndescription: All other issues\nlabels: [\"status: triage\"]\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n    validations:\n      required: true\n  - type: textarea\n    id: code-sample\n    attributes:\n      label: Code sample\n      description: Provide a code sample if applicable \n      render: C#\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.yml",
    "content": "name: Question\ndescription: Ask a question\nlabels: [\"type: question\", \"status: triage\"]\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Question\n      description: Outline the question you have\n    validations:\n      required: true\n  - type: textarea\n    id: code-sample\n    attributes:\n      label: Code sample\n      description: Provide a code sample if applicable \n      render: C#\n    validations:\n      required: false\n  - type: input\n    id: version\n    attributes:\n      label: Version\n      description: What MvvmBlazor version are you using?\n    validations:\n      required: true\n  - type: dropdown\n    id: blazor-type\n    attributes:\n      label: Are you using Blazor WASM or Blazor Server?\n      multiple: false\n      options:\n        - Blazor WASM\n        - Blazor Server\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/workflows/build.yaml",
    "content": "on:\n  push:\n    branches:\n      - master\n  pull_request:\n    branches:\n      - master\n    paths:\n      - 'src/**/*'\n      - 'samples/**/*'\n      - '.github/workflows/**/*'\n\nname: Build\n\njobs:\n\n  build:\n    name: Build\n    runs-on: ubuntu-latest\n    steps:\n\n      - uses: actions/checkout@master\n\n      - name: Setup .NET\n        uses: actions/setup-dotnet@master\n        with:\n          dotnet-version: '6.0.x'\n\n      - name: Build\n        run: dotnet build --configuration Release -p:ContinuousIntegrationBuild=true -p:TreatWarningsAsErrors=true src\n\n      - name: Test\n        run: dotnet test -p:ContinuousIntegrationBuild=true -p:CollectCoverage=true -p:CoverletOutputFormat=lcov -p:CoverletOutput=$GITHUB_WORKSPACE/coverage.lcov src\n\n      - name: Upload coverage\n        uses: romeovs/lcov-reporter-action@master\n        if: github.event.pull_request.base.ref == 'master'\n        with:\n          lcov-file: coverage.lcov\n          delete-old-comments: true\n\n      - name: Pack\n        run: dotnet pack --configuration Release -p:ContinuousIntegrationBuild=true -p:SymbolPackageFormat=snupkg src -o out\n\n      - name: Upload artifacts\n        uses: actions/upload-artifact@v2\n        with:\n          name: packages\n          path: out/*\n"
  },
  {
    "path": ".github/workflows/release.yaml",
    "content": "on:\n  release:\n    types: [ published ]\n\nname: Release\n\njobs:\n\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n    steps:\n\n      - uses: actions/checkout@master\n\n      - name: Setup .NET\n        uses: actions/setup-dotnet@master\n        with:\n          dotnet-version: '6.0.x'\n\n      - name: Build\n        run: dotnet build -p:ContinuousIntegrationBuild=true -p:TreatWarningsAsErrors=true --configuration Release src\n\n      - name: Test\n        run: dotnet test --configuration Release src\n\n      - name: Publish\n        run: >\n          dotnet nuget add source --username $GITHUB_REPOSITORY_OWNER --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github \"https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json\";\n          export VERSION=$(git describe --long --tags --match 'v*' | sed 's/v//' | sed -E 's/[-].+//g');\n          echo $VERSION;\n          dotnet pack --configuration Release --include-source -p:ContinuousIntegrationBuild=true -p:Version=$VERSION -o out src;\n          cd out;\n          rm MvvmBlazor.CodeGenerators.*.symbols.nupkg;\n          dotnet nuget push *.nupkg --skip-duplicate --force-english-output -k ${{ secrets.NUGET_KEY }} -s https://api.nuget.org/v3/index.json;\n          dotnet nuget push *.nupkg --skip-duplicate --force-english-output -s https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json;\n\n      - name: Upload artifacts\n        if: always()\n        uses: actions/upload-artifact@v2\n        with:\n          name: packages\n          path: out/*\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# Tye\n.tye/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\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*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\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# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\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# Note: 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# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\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~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\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\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\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# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n##\n## Visual studio for Mac\n##\n\n\n# globs\nMakefile.in\n*.userprefs\n*.usertasks\nconfig.make\nconfig.status\naclocal.m4\ninstall-sh\nautom4te.cache/\n*.tar.gz\ntarballs/\ntest-results/\n\n# Mac bundle stuff\n*.dmg\n*.app\n\n# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore\n# Windows thumbnail cache files\nThumbs.db\nehthumbs.db\nehthumbs_vista.db\n\n# Dump file\n*.stackdump\n\n# Folder config file\n[Dd]esktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n\n##\n## Visual Studio Code\n##\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Christian Klemm\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "MvvmBlazor\n================\n[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fchris579%2FMvvmBlazor%2Fbadge&style=flat-square)](https://github.com/chris579/MvvmBlazor/actions) [![NuGet](https://img.shields.io/nuget/v/MvvmBlazor.svg?style=flat-square)](https://www.nuget.org/packages/MvvmBlazor) [![NuGet](https://img.shields.io/nuget/dt/MvvmBlazor)](https://www.nuget.org/packages/MvvmBlazor) \n\n\nMvvmBlazor is a small framework for building Blazor WebAssembly and Blazor Server apps. With its easy-to-use MVVM pattern you\ncan increase your development speed while minimising the effort required to make it work.\n\n## Getting started\n\nMvvmBlazor is available on [NuGet](https://www.nuget.org/packages/MvvmBlazor). You will need **.NET 6** to use this\nlibrary.\n\nThe library needs to be added to the DI container in order to use it. This is done in your `Startup` class.\n\n```c#\npublic class Startup\n{\n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddMvvm();\n    }\n}\n```\n\n## Usage\n\n### Components\n\nComponents need to inherit the base class `MvvmBlazor.Components.MvvmComponentBase` if you want to inject your view\nmodel manually. You can set a binding on any view model you like to.\n\nIf you want full support use `MvvmBlazor.Components.MvvmComponentBase<T>` and specify your view model type as a generic\nargument.\nYour view model will get auto injected into the component and set as a binding context.\n\n#### BindingSource\n\nThe binding source is the default source object a binding will be made to. It is set automatically when using the base\nclass `MvvmBlazor.Components.MvvmComponentBase<T>` where `T` is your view model type. You can access it via\nthe `BindingContext` property in your component.\n\n#### Bindings\n\nBindings are achieved via the `Bind` method in the component. If the value of the bound property has changed the\ncomponent will be told to rerender automatically. In this example we assume that the class `ClockViewModel` has a\nproperty called `DateTime`.\n\n```c#\n@inherits MvvmComponentBase<ClockViewModel>\n\nCurrent time: @Bind(x => x.DateTime)\n```\n\nBindings can also be done by specifying the binding source explicitly:\n\n```c#\n@inherits MvvmComponentBase\n@inject ClockViewModel ClockViewModel\n\nCurrent time: @Bind(ClockViewModel, x => x.DateTime)\n```\n\nBindings also handle background updating automatically. No need to invoke the main thread.\n\n#### Collection Bindings\n\nIf you want to have a collection that automatically notifies the component when it has changed you should use one that\nimplements `INotifyCollectionChanged`, e.g. `ObservableCollection<T>`.\n\nIn List scenarios you often chain view models to achieve bindings for every list element on it's corresponding view\nmodel. Given this view models\n\n```c#\nclass MainViewModel\n{\n    public ObservableCollection<SubViewModel> Items { get; }\n}\n\nclass SubViewModel\n{\n    private string _name;\n    public string Name\n    {\n        get => _name;\n        set => Set(ref, _name, value);\n    }\n}\n```\n\nyou can use bindings on your sub view models like this\n\n```c#\n@foreach (var item in Bind(x => x.Items))\n{\n    <label>@Bind(item, x => x.Name)</label>\n}\n```\n\nThis way the name of every list item is bound to it's corresponding entry in the view. If you change the name on any\nlist item, it will be changed in the view too.\n\n### EventHandlers\n\nEvent handles work just the way they work in blazor. When you use the non generic base class you can bind any injected\nobject on them.\n\n```c#\n@inherits MvvmComponentBase\n@inject CounterViewModel CounterViewModel\n\n<button @onclick=\"@CounterViewModel.IncrementCount\">Click me</button>\n```\n\nWhen using the generic base class you can directly bind them to your binding context.\n\n```c#\n@inherits MvvmComponentBase<CounterViewModel>\n\n<button @onclick=\"@BindingContext.IncrementCount\">Click me</button>\n```\n\n### ViewModel\n\nView models need to inherit the base class `MvvmBlazor.ViewModel.ViewModelBase`.\n\nIf you register a view model as scoped it will be tied to the lifetime of the component and disposed when the component is disposed.\nThis allows you to inject scoped services that should be short lived (e.g. a `DbContext`) without the need for using a factory.\n\nNote: Some services need to be resolved from the root service provider (e.g. `NavigationManager`). To do this you can access the root service provider via the `RootServiceProvider` property.\n\n#### Property implementation\n\nBindable properties need to raise the `PropertyChanged` event on the ViewModel.\n\nThe `Set`-Method is performing an equality check and is raising this event if needed. An example implementation could\nlook like this:\n\n```c#\nprivate int _currentCount;\npublic int CurrentCount\n{\n    get => _currentCount;\n    set => Set(ref _currentCount, value);\n}\n```\n\nAs an alternative you can leverage the power of source generators to do the tedious work for you.\nJust declare a private field inside of a view model and decorate if with the `Notify` attribute. The matching property will be auto generated for you.\n```c#\n[Notify]\nprivate int _currentCount;\n```\nNote: Some third party IDEs may not recognize source generators at the current point. They could report that the property does not exist while the project builds fine.\n\n#### Lifecycle methods\n\nView models have access to the same lifecycle methods as a component when they are set as a binding context. They are\ndocumented [here](https://docs.microsoft.com/en-us/aspnet/core/blazor/components?view=aspnetcore-3.0#lifecycle-methods).\n\n#### Parameters\n\nParameters are automatically populated to the view model. Declare a parameter in your component\n\n```c#\n@code {\n    [Parameter]\n    public string Name { get; set; }\n}\n```\n\nand declare the same parameter in your view model\n\n```c#\nclass ViewModel: ViewModelBase\n{\n    [Parameter]\n    public string Name { get; set; }\n}\n```\n\nCascading parameters are supported as well.\nThe parameter will be passed when parameters are set on the component. More information regarding the lifecycle can be\nfound in\nthe [Microsoft Documentation](https://docs.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-6.0#lifecycle-events)\n.\n\n##### Type conversion\n\nWhen binding parameters in a component Blazor restricts you to a finite list of primitive types you can use. In some\nscenarios you might want to bind to a strong type and perform automatic conversions to it. A typical use case for this\nwould be a strongly typed identifier that you use in your application.\n\nView model parameters support type conversion\nusing [`TypeConverter`](https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.typeconverter?view=net-6.0).\nYour component parameters still needs to be a supported primitive type, however your view model parameter can be\nstrongly typed and will get auto converted. An example for this can be found in the TypedParameter sample.\n\n#### Dispose\n\nSince ViewModels are being injected through dependency injection in the scope of the component the\nDI [takes care](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0#disposal-of-services)\nof disposing ViewModels.\n\n## Advanced scenarios\nSome libraries may force you to use a different base class than `MvvmComponentBase`.\nTo solve this issue you can create a custom mvvm component using source generators.\n\nCreate a partial class and decorate it with the `MvvmComponent` attribute.\n\n```c#\n[MvvmComponent]\npublic abstract partial class CustomComponentBase : UiLibraryComponentBase\n{\n\n}\n```\n\nAs a reference point see [`MvvmComponentBase`](https://github.com/klemmchr/MvvmBlazor/blob/master/src/MvvmBlazor.Core/Components/MvvmComponentBase.cs) and [`MvvmComponentBase<T>`](https://github.com/klemmchr/MvvmBlazor/blob/master/src/MvvmBlazor.Core/Components/MvvmComponentBaseT.cs).\nBoth are generated by a source generator as well.\n\n## Examples\n\nExamples for Blazor and Serverside Blazor can be\nfound [here](https://github.com/chris579/MvvmBlazor/tree/master/samples).\n\nYou will find several projects in there\n\n- *BlazorServersideSample*\n  A server for the blazor serverside sample\n- *BlazorClientsideSample.Server*\n  The server for the blazor clientside sample\n- *BlazorClientsideSample.Client*\n  The client for the blazor clientside sample\n\nThese projects act as wrapper projects for the main functionality that is shared among these examples.\n\n- *BlazorSample.Components*\n  The components and pages for the samples\n- *BlazorSample.ViewModels*\n  The view models for the pages\n- *BlazorSample.Domain*\n  Domain logic, stuff shared between components and view models\n\n"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/App.razor",
    "content": "﻿<Router AppAssembly=\"@typeof(BlazorSample.Components._Imports).Assembly\">\n    <Found Context=\"routeData\">\n        <RouteView RouteData=\"@routeData\" DefaultLayout=\"@typeof(MainLayout)\"/>\n    </Found>\n    <NotFound>\n        <LayoutView Layout=\"@typeof(MainLayout)\">\n            <p>Sorry, there's nothing at this address.</p>\n        </LayoutView>\n    </NotFound>\n</Router>"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/BlazorClientsideSample.Client.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.BlazorWebAssembly\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <BlazorWebAssemblyEnableLinking>false</BlazorWebAssemblyEnableLinking>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Microsoft.AspNetCore.Components.WebAssembly\" Version=\"6.0.2\"/>\n        <PackageReference Include=\"Microsoft.AspNetCore.Components.WebAssembly.DevServer\" Version=\"6.0.2\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\"/>\n        <ProjectReference Include=\"..\\BlazorSample.Components\\BlazorSample.Components.csproj\"/>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/Program.cs",
    "content": "﻿using BlazorClientsideSample.Client.Services;\nusing BlazorSample.Components.Extensions;\nusing BlazorSample.Domain.Extensions;\nusing BlazorSample.Domain.Services;\nusing BlazorSample.ViewModels.Extensions;\nusing Microsoft.AspNetCore.Components.WebAssembly.Hosting;\n\nnamespace BlazorClientsideSample.Client;\n\npublic class Program\n{\n    public static async Task Main(string[] args)\n    {\n        var builder = WebAssemblyHostBuilder.CreateDefault(args);\n\n        builder.RootComponents.Add<App>(\"#app\");\n\n        builder.Services.AddMvvm();\n        builder.Services.AddDomain().AddComponents().AddViewModels();\n\n        builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });\n\n        builder.Services.AddSingleton<IWeatherForecastGetter, WeatherForecastGetter>();\n\n        var host = builder.Build();\n\n        await host.RunAsync();\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/Properties/launchSettings.json",
    "content": "{\n    \"profiles\": {\n        \"BlazorClientsideSample.Client\": {\n            \"commandName\": \"Project\",\n            \"environmentVariables\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n            },\n            \"applicationUrl\": \"http://localhost:50069/\"\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/Services/WeatherForecastGetter.cs",
    "content": "﻿using System.Net.Http.Json;\nusing BlazorSample.Domain.Entities;\nusing BlazorSample.Domain.Services;\n\nnamespace BlazorClientsideSample.Client.Services;\n\npublic class WeatherForecastGetter : IWeatherForecastGetter\n{\n    private readonly HttpClient _httpClient;\n\n    public WeatherForecastGetter(HttpClient httpClient)\n    {\n        _httpClient = httpClient;\n    }\n\n    public Task<IEnumerable<WeatherForecastEntity>> GetForecasts()\n    {\n        return _httpClient.GetFromJsonAsync<IEnumerable<WeatherForecastEntity>>(\"WeatherForecast\")!;\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/_Imports.razor",
    "content": "﻿@using System.Net.Http\n@using Microsoft.AspNetCore.Components.Forms\n@using Microsoft.AspNetCore.Components.Routing\n@using Microsoft.AspNetCore.Components.Web\n@using Microsoft.JSInterop\n@using MvvmBlazor.Components\n@using BlazorSample.Components.Shared"
  },
  {
    "path": "samples/BlazorClientsideSample.Client/wwwroot/index.html",
    "content": "﻿<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"utf-8\"/>\n    <meta content=\"width=device-width\" name=\"viewport\"/>\n    <title>BlazorSample</title>\n    <base href=\"/\"/>\n    <link href=\"_content/BlazorSample.Components/site.css\" rel=\"stylesheet\"/>\n    <script src=\"_content/MatBlazor/dist/matBlazor.js\"></script>\n    <link href=\"_content/MatBlazor/dist/matBlazor.css\" rel=\"stylesheet\"/>\n</head>\n<body>\n<div id=\"app\">Loading...</div>\n\n<script src=\"_framework/blazor.webassembly.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "samples/BlazorClientsideSample.Server/BlazorClientsideSample.Server.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n    <ItemGroup>\n\n        <PackageReference Include=\"Microsoft.AspNetCore.Components.WebAssembly.Server\" Version=\"6.0.2\"/>\n        <PackageReference Include=\"Microsoft.AspNetCore.Mvc.NewtonsoftJson\" Version=\"6.0.2\"/>\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\"/>\n        <ProjectReference Include=\"..\\BlazorClientsideSample.Client\\BlazorClientsideSample.Client.csproj\"/>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorClientsideSample.Server/Controllers/WeatherForecastController.cs",
    "content": "﻿using BlazorSample.Domain.Entities;\nusing Microsoft.AspNetCore.Mvc;\n\nnamespace BlazorClientsideSample.Server.Controllers;\n\n[ApiController]\n[Route(\"[controller]\")]\npublic class WeatherForecastController : ControllerBase\n{\n    private static readonly string[] Summaries =\n    {\n        \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\"\n    };\n\n    [HttpGet]\n    public IEnumerable<WeatherForecastEntity> Get()\n    {\n        var rng = new Random();\n        return Enumerable.Range(1, 5)\n            .Select(\n                index => new WeatherForecastEntity\n                {\n                    Date = DateTime.Now.AddDays(index),\n                    TemperatureC = rng.Next(-20, 55),\n                    Summary = Summaries[rng.Next(Summaries.Length)]\n                }\n            )\n            .ToArray();\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Server/Program.cs",
    "content": "﻿using Microsoft.AspNetCore;\n\nnamespace BlazorClientsideSample.Server;\n\npublic class Program\n{\n    public static void Main(string[] args)\n    {\n        BuildWebHost(args).Run();\n    }\n\n    public static IWebHost BuildWebHost(string[] args)\n    {\n        return WebHost.CreateDefaultBuilder(args)\n            .UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build())\n            .UseStartup<Startup>()\n            .Build();\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Server/Properties/launchSettings.json",
    "content": "{\n    \"profiles\": {\n        \"BlazorClientsideSample.Server\": {\n            \"commandName\": \"Project\",\n            \"launchBrowser\": true,\n            \"environmentVariables\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n            },\n            \"applicationUrl\": \"http://localhost:52345/\"\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorClientsideSample.Server/Startup.cs",
    "content": "using Microsoft.AspNetCore.ResponseCompression;\n\nnamespace BlazorClientsideSample.Server;\n\npublic class Startup\n{\n    // This method gets called by the runtime. Use this method to add services to the container.\n    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940\n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddMvc().AddNewtonsoftJson();\n        services.AddResponseCompression(\n            opts =>\n            {\n                opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { \"application/octet-stream\" });\n            }\n        );\n    }\n\n    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n    {\n        app.UseResponseCompression();\n\n        if (env.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n            app.UseWebAssemblyDebugging();\n        }\n\n        app.UseBlazorFrameworkFiles();\n        app.UseStaticFiles();\n\n        app.UseRouting();\n\n        app.UseEndpoints(\n            endpoints =>\n            {\n                endpoints.MapDefaultControllerRoute();\n                endpoints.MapFallbackToFile(\"index.html\");\n            }\n        );\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Components/BlazorSample.Components.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk.Razor\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <RazorLangVersion>3.0</RazorLangVersion>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n\n    <ItemGroup>\n        <PackageReference Include=\"MatBlazor\" Version=\"2.8.0\" />\n        <PackageReference Include=\"Microsoft.AspNetCore.Components\" Version=\"6.0.2\" />\n        <PackageReference Include=\"Microsoft.AspNetCore.Components.Web\" Version=\"6.0.2\" />\n    </ItemGroup>\n\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\BlazorSample.ViewModels\\BlazorSample.ViewModels.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\" OutputItemType=\"Analyzer\" ReferenceOutputAssembly=\"false\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorSample.Components/Extensions/ServiceCollectionExtensions.cs",
    "content": "﻿using BlazorSample.Components.Pages;\nusing BlazorSample.Domain.Extensions;\nusing MatBlazor;\nusing Microsoft.Extensions.DependencyInjection;\nusing Index = BlazorSample.Components.Pages.Index;\n\nnamespace BlazorSample.Components.Extensions;\n\npublic static class ServiceCollectionExtensions\n{\n    public static IServiceCollection AddComponents(this IServiceCollection serviceCollection)\n    {\n        serviceCollection.AddNavigationItem<Index>(\"Index\", MatIconNames.Home);\n        serviceCollection.AddNavigationItem<Counter>(\"Counter\", MatIconNames.Add);\n        serviceCollection.AddNavigationItem<WeatherForecasts>(\"Weather forecasts\", MatIconNames.Cloud);\n        serviceCollection.AddNavigationItem<Clock>(\"Clock\", MatIconNames.Alarm);\n        serviceCollection.AddNavigationItem<Parameters>(\"Parameters\", MatIconNames.List);\n        serviceCollection.AddNavigationItem<TypedParameters>(\"Typed Parameters\", MatIconNames.List);\n\n        return serviceCollection;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/Clock.razor",
    "content": "﻿@page \"/clock\"\n@inherits CustomBaseComponent<ClockViewModel>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            Having values updating in the background is no hassle. No need to manually invoke\n            <pre style=\"display: inline\">StateHasChanged()</pre> on the component inside it's synchronization context.\n            That's done for you! Just make sure to update your values using the <pre style=\"display: inline\">Set</pre> method in your view model.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<MatBody2>\n    This component demonstrates updating from a background task without user interaction.\n</MatBody2>\n<br/>\n<MatBody2>\n    Current time: @Bind(x => x.DateTime)\n</MatBody2>"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/Counter.razor",
    "content": "﻿@page \"/counter\"\n@inherits CustomBaseComponent<CounterViewModel>\n@inject ClockViewModel ClockViewModel\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            The view model gets auto injected and can be accessed with the property <pre style=\"display: inline\">BindingContext</pre>.\n            You can use this property to bind event handlers on your controls.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n\n<MatBody2>Current count: @Bind(x => x.CurrentCount)</MatBody2>\n\n<MatButton OnClick=\"@BindingContext.IncrementCount\" Raised=\"true\">Click me</MatButton>\n\n<br/>\n<br/>\n<br/>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            You can also bind additional view models that you simply inject by yourself.\n            The lifecycle methods on such view models will not be invoked by this component.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<MatBody2>Current time: @Bind(ClockViewModel, x => x.DateTime)</MatBody2>"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/Index.razor",
    "content": "﻿@page \"/\"\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            Explore the tabs on the left to see some examples and explore MvvmBlazor!\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/Parameters.razor",
    "content": "﻿@page \"/parameters/{name}\"\n@inherits CustomBaseComponent<ParametersViewModel>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            You can also pass down parameters to your view model. If you set a binding context you can\n            declare your parameters just as you would before but you also declare them in your view model.\n            They will be passed down to it automatically.\n            Enter a new value down below and click the button. See how the url changed and the parameter is shown.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<MatBody2>My Name is @Bind(x => x.Name)</MatBody2>\n<br/>\n\n<MatTextField @bind-Value=\"@BindingContext.NewName\" Label=\"New name\"></MatTextField>\n<MatButton OnClick=\"@BindingContext.NavigateToNewName\" Raised=\"true\">Navigate</MatButton>\n\n<br/>\n<br/>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            Cascading parameters are supported as well.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<CascadingValue Value=\"@(\"Marc Foo Bar\")\">\n    <CascadingComponent></CascadingComponent>\n</CascadingValue>\n\n@code {\n\n    [Parameter]\n    public string Name { get; set; } = \"Marc\";\n\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/TypedParameters.razor",
    "content": "﻿@page \"/typed-parameters/{Id}\"\n@inherits CustomBaseComponent<TypedParametersViewModel>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            Converting parameter types is supported out of the box.\n            Visit the <a href=\"https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.typeconverter?view=net-6.0\" target=\"_blank\">Microsoft Documentation</a> to find out more about TypeConverter.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<MatBody2>Id value @Bind(x => x.Id)</MatBody2>\n<br/>\n\n<MatButton OnClick=\"@BindingContext.NavigateToRandomId\" Raised=\"true\">Navigate to random id</MatButton>\n\n@code {\n\n    [Parameter]\n    public string? Id { get; set; }\n\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Pages/WeatherForecasts.razor",
    "content": "﻿@page \"/fetchdata\"\n\n@inherits CustomBaseComponent<WeatherForecastsViewModel>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            To use a view model with your component simply inherit from the base class\n            <pre style=\"display: inline\">MvvmComponentBase</pre> and specify your view model type for this component as a generic argument.\n            Your view model will have access to all lifecycle methods you also have on your component.\n            As soon as any value changes via the <pre style=\"display: inline\">Set</pre> method on your view model the component will refresh if needed.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n<MatCard>\n    <MatCardContent>\n        <MatSubtitle1>\n            In list scenarios you often nest view models to achieve bindings on the list items. This is especially needed when the data of the item changes.\n            You can click the randomize button and see that the list gets updated.\n        </MatSubtitle1>\n    </MatCardContent>\n</MatCard>\n<br/>\n\n@if (Bind(x => x.Forecasts) == null)\n{\n    <MatProgressBar Indeterminate=\"true\"></MatProgressBar>\n}\nelse\n{\n    <MatButton Raised=\"true\" OnClick=\"@BindingContext.RandomizeData\">Randomize</MatButton>\n    <br/>\n\n    <MatList SingleSelection=\"true\" TwoLine=\"true\">\n        @foreach (var forecast in Bind(x => x.Forecasts)!)\n        {\n            <MatListItem>\n                <MatListItemText>\n                    <MatListItemPrimaryText>@forecast.Date.ToShortDateString() @forecast.Summary</MatListItemPrimaryText>\n                    <MatListItemSecondaryText>@Bind(forecast, x => x.TemperatureC)°C (@Bind(forecast, x => x.TemperatureF)°F)</MatListItemSecondaryText>\n                </MatListItemText>\n            </MatListItem>\n        }\n    </MatList>\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Shared/CascadingComponent.razor",
    "content": "﻿@inherits CustomBaseComponent<CascadingViewModel>\n\n<MatBody2>Cascading value is @Bind(x => x.Name)</MatBody2>\n\n@code {\n\n    [CascadingParameter]\n    public string? Name { get; set; }\n\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Shared/CustomBaseComponent.cs",
    "content": "﻿using Microsoft.AspNetCore.Components;\nusing MvvmBlazor;\n\nnamespace BlazorSample.Components.Shared;\n\n[MvvmComponent]\npublic abstract partial class CustomBaseComponent<T> : CustomBaseComponent\n{\n\n}\n\n[MvvmComponent]\npublic abstract partial class CustomBaseComponent : ComponentBase\n{\n\n}"
  },
  {
    "path": "samples/BlazorSample.Components/Shared/MainLayout.razor",
    "content": "﻿@inherits LayoutComponentBase\n\n<Navbar>\n    @Body\n</Navbar>"
  },
  {
    "path": "samples/BlazorSample.Components/Shared/Navbar.razor",
    "content": "﻿@inherits MvvmComponentBase<NavbarViewModel>\n\n<MatDrawerContainer Class=\"navbar\">\n    <MatDrawer @bind-Opened=\"@BindingContext.IsMenuOpen\" Class=\"left-sidebar\">\n        <MatNavMenu>\n            @foreach (var item in Bind(x => x.NavbarItems))\n            {\n                <MatNavItem Href=\"@item.Template\" Selected=\"@Bind(item, x => x.IsActive)\">\n                    @if (!string.IsNullOrEmpty(item.Icon))\n                    {\n                        <MatIcon Icon=\"@item.Icon\" class=\"icon\"></MatIcon>\n                    }\n\n                    @item.DisplayName\n                </MatNavItem>\n            }\n        </MatNavMenu>\n    </MatDrawer>\n    <MatDrawerContent>\n        <MatAppBarContainer>\n            <MatAppBar Fixed=\"true\">\n                <MatAppBarRow>\n                    <MatAppBarSection>\n                        <MatIconButton Icon=\"menu\" OnClick=\"@BindingContext.ToggleMenu\"></MatIconButton>\n                        <MatAppBarTitle>MvvmBlazor Sample App</MatAppBarTitle>\n                    </MatAppBarSection>\n                </MatAppBarRow>\n            </MatAppBar>\n            <MatAppBarContent>\n                <div class=\"content-container\">\n                    @ChildContent\n                </div>\n            </MatAppBarContent>\n        </MatAppBarContainer>\n    </MatDrawerContent>\n</MatDrawerContainer>\n\n@code\n{\n    [Parameter]\n    public RenderFragment? ChildContent { get; set; }\n\n}"
  },
  {
    "path": "samples/BlazorSample.Components/_Imports.razor",
    "content": "﻿@using Microsoft.AspNetCore.Components.Web\n@using MvvmBlazor.Components\n@using BlazorSample.ViewModels\n@using BlazorSample.ViewModels.Navbar\n@using Microsoft.AspNetCore.Components.Routing\n@using MatBlazor\n@using BlazorSample.Components.Shared"
  },
  {
    "path": "samples/BlazorSample.Components/wwwroot/site.css",
    "content": "﻿/* http://meyerweb.com/eric/tools/css/reset/\n   v4.0 | 20180602\n   License: none (public domain)\n*/\n\nhtml, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, big, cite, code,\ndel, dfn, em, img, ins, kbd, q, s, samp,\nsmall, strike, strong, sub, sup, tt, var,\nb, u, i, center,\ndl, dt, dd, ol, ul, li,\nfieldset, form, label, legend,\ntable, caption, tbody, tfoot, thead, tr, th, td,\narticle, aside, canvas, details, embed,\nfigure, figcaption, footer, header, hgroup,\nmain, menu, nav, output, ruby, section, summary,\ntime, mark, audio, video {\n    border: 0;\n    font: inherit;\n    font-size: 100%;\n    margin: 0;\n    padding: 0;\n    vertical-align: baseline;\n}\n\n/* HTML5 display-role reset for older browsers */\n\narticle, aside, details, figcaption, figure,\nfooter, header, hgroup, main, menu, nav, section {\n    display: block;\n}\n\n/* HTML5 hidden-attribute fix for newer browsers */\n\n*[hidden] {\n    display: none;\n}\n\nbody {\n    line-height: 1;\n}\n\nol, ul {\n    list-style: none;\n}\n\nblockquote, q {\n    quotes: none;\n}\n\nblockquote:before, blockquote:after,\nq:before, q:after {\n    content: '';\n    content: none;\n}\n\ntable {\n    border-collapse: collapse;\n    border-spacing: 0;\n}\n\nhtml, body, app {\n    height: 100%;\n}\n\n.mdc-text-field {\n    width: 100% !important;\n}\n\n.mdc-card__primary-action {\n    padding: 0.5rem;\n}\n\n.navbar {\n    height: 100vh;\n    width: 100vw;\n}\n\n.navbar .left-sidebar {\n    user-select: none;\n}\n\n.navbar .icon {\n    margin-right: 0.5rem;\n}\n\n.navbar .content-container {\n    margin: 1rem;\n}\n\n.navbar aside:focus {\n    outline: none;\n}\n\n.navbar .mdc-drawer__content:focus {\n    outline: none;\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/BlazorSample.Domain.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <PackageReference Include=\"Microsoft.AspNetCore.Components\" Version=\"6.0.2\"/>\n        <PackageReference Include=\"Microsoft.Extensions.DependencyInjection.Abstractions\" Version=\"6.0.0\"/>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorSample.Domain/Converters/IdTypeConverter.cs",
    "content": "﻿using System.ComponentModel;\nusing System.Globalization;\nusing BlazorSample.Domain.Entities;\n\nnamespace BlazorSample.Domain.Converters;\n\npublic class IdTypeConverter : TypeConverter\n{\n    public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)\n    {\n        return sourceType == typeof(string);\n    }\n\n    public override object? ConvertTo(\n        ITypeDescriptorContext? context,\n        CultureInfo? culture,\n        object? value,\n        Type destinationType)\n    {\n        return value is not string s || !Guid.TryParse(s, out var guid) ? null : new IdType(guid);\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Entities/IdType.cs",
    "content": "﻿using System.ComponentModel;\nusing System.Text.Json;\nusing BlazorSample.Domain.Converters;\n\nnamespace BlazorSample.Domain.Entities;\n\n[TypeConverter(typeof(IdTypeConverter))]\npublic record IdType(Guid Value)\n{\n    public override string ToString()\n    {\n        return JsonSerializer.Serialize(this);\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Entities/WeatherForecastEntity.cs",
    "content": "namespace BlazorSample.Domain.Entities;\n\npublic class WeatherForecastEntity\n{\n    public DateTime Date { get; set; }\n\n    public int TemperatureC { get; set; }\n\n    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);\n\n    public string? Summary { get; set; }\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Extensions/ServiceCollectionExtensions.cs",
    "content": "﻿using BlazorSample.Domain.Services.Navbar;\nusing Microsoft.AspNetCore.Components;\nusing Microsoft.Extensions.DependencyInjection;\n\nnamespace BlazorSample.Domain.Extensions;\n\npublic static class ServiceCollectionExtensions\n{\n    public static IServiceCollection AddNavigationItem<TPage>(\n        this IServiceCollection serviceCollection,\n        string title,\n        string? icon = null) where TPage : ComponentBase\n    {\n        serviceCollection.AddSingleton(new NavbarItem(typeof(TPage), title, icon));\n        return serviceCollection;\n    }\n\n    public static IServiceCollection AddDomain(this IServiceCollection serviceCollection)\n    {\n        serviceCollection.AddScoped<INavbarService, NavbarService>();\n        return serviceCollection;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Services/IWeatherForecastGetter.cs",
    "content": "﻿using BlazorSample.Domain.Entities;\n\nnamespace BlazorSample.Domain.Services;\n\npublic interface IWeatherForecastGetter\n{\n    Task<IEnumerable<WeatherForecastEntity>> GetForecasts();\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Services/Navbar/NavbarItem.cs",
    "content": "﻿namespace BlazorSample.Domain.Services.Navbar;\n\npublic class NavbarItem\n{\n    public string? Icon { get; }\n    public Type Page { get; }\n    public string DisplayName { get; }\n    public string? Template { get; set; }\n\n    public NavbarItem(Type page, string displayName, string? icon)\n    {\n        Page = page;\n        DisplayName = displayName;\n        Icon = icon;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.Domain/Services/Navbar/NavbarService.cs",
    "content": "﻿using System.Collections.ObjectModel;\nusing System.Reflection;\nusing Microsoft.AspNetCore.Components;\n\nnamespace BlazorSample.Domain.Services.Navbar;\n\npublic interface INavbarService\n{\n    IReadOnlyList<NavbarItem> NavbarItems { get; }\n}\n\npublic class NavbarService : INavbarService\n{\n    private readonly List<NavbarItem> _navbarItems = new();\n\n    public NavbarService(IEnumerable<NavbarItem> navbarItems)\n    {\n        NavbarItems = new ReadOnlyCollection<NavbarItem>(_navbarItems);\n        LoadComponents(navbarItems);\n    }\n\n    public IReadOnlyList<NavbarItem> NavbarItems { get; }\n\n    private void LoadComponents(IEnumerable<NavbarItem> navbarItems)\n    {\n        foreach (var item in navbarItems)\n        {\n            if (!(item.Page.BaseType == typeof(ComponentBase) ||\n                  typeof(ComponentBase).IsAssignableFrom(item.Page.BaseType)))\n            {\n                throw new InvalidOperationException(\n                    $\"NavItem {item.DisplayName}:{item.Page.FullName} is not a component\"\n                );\n            }\n\n            var routeAttribute = item.Page.GetCustomAttribute<RouteAttribute>();\n            if (routeAttribute == null)\n            {\n                throw new InvalidOperationException(\n                    $\"NavItem {item.DisplayName}:{item.Page.FullName} has no {nameof(RouteAttribute)}\"\n                );\n            }\n\n            item.Template = routeAttribute.Template;\n            _navbarItems.Add(item);\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/BlazorSample.ViewModels.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\" />\n        <ProjectReference Include=\"..\\BlazorSample.Domain\\BlazorSample.Domain.csproj\" />\n    </ItemGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\" OutputItemType=\"Analyzer\" ReferenceOutputAssembly=\"false\" />\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorSample.ViewModels/CascadingViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic class CascadingViewModel : ViewModelBase\n{\n    [CascadingParameter]\n    public string? Name { get; set; }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/ClockViewModel.cs",
    "content": "﻿using Timer = System.Timers.Timer;\n\nnamespace BlazorSample.ViewModels;\n\npublic partial class ClockViewModel : ViewModelBase, IDisposable\n{\n    private readonly Timer _timer;\n\n    [Notify] private DateTime _dateTime = DateTime.Now;\n\n    public ClockViewModel()\n    {\n        _timer = new Timer(TimeSpan.FromSeconds(1).TotalMilliseconds);\n        _timer.Elapsed += TimerOnElapsed;\n        _timer.Start();\n    }\n\n    public void Dispose()\n    {\n        GC.SuppressFinalize(this);\n        Dispose(true);\n    }\n\n    private void TimerOnElapsed(object? sender, ElapsedEventArgs e)\n    {\n        DateTime = DateTime.Now;\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _timer.Dispose();\n        }\n    }\n\n    ~ClockViewModel()\n    {\n        Dispose(false);\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/CounterViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic partial class CounterViewModel : ViewModelBase\n{\n    [Notify] private int _currentCount;\n\n    public void IncrementCount()\n    {\n        CurrentCount++;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/Extensions/ServiceCollectionExtensions.cs",
    "content": "﻿using BlazorSample.ViewModels.Navbar;\n\nnamespace BlazorSample.ViewModels.Extensions;\n\npublic static class ServiceCollectionExtensions\n{\n    public static IServiceCollection AddViewModels(this IServiceCollection serviceCollection)\n    {\n        serviceCollection.AddTransient<WeatherForecastsViewModel>();\n        serviceCollection.AddTransient<CounterViewModel>();\n        serviceCollection.AddTransient<ClockViewModel>();\n        serviceCollection.AddTransient<ParametersViewModel>();\n        serviceCollection.AddScoped<NavbarViewModel>();\n        serviceCollection.AddScoped<TypedParametersViewModel>();\n        serviceCollection.AddTransient<CascadingViewModel>();\n\n        return serviceCollection;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/GlobalUsings.cs",
    "content": "﻿global using System.Collections.ObjectModel;\nglobal using BlazorSample.Domain.Services;\nglobal using MvvmBlazor;\nglobal using MvvmBlazor.ViewModel;\nglobal using System.Timers;\nglobal using Microsoft.AspNetCore.Components;\nglobal using Microsoft.Extensions.DependencyInjection;\nglobal using BlazorSample.Domain.Entities;"
  },
  {
    "path": "samples/BlazorSample.ViewModels/Navbar/NavbarItemViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels.Navbar;\n\npublic class NavbarItemViewModel : ViewModelBase\n{\n    private bool _isActive;\n\n    public string DisplayName { get; }\n\n    public string Template { get; }\n\n    public string? Icon { get; set; }\n\n    public bool IsActive\n    {\n        get => _isActive;\n        set => Set(ref _isActive, value, nameof(IsActive));\n    }\n\n    public NavbarItemViewModel(string displayName, string template, string? icon)\n    {\n        DisplayName = displayName;\n        Template = template;\n        Icon = icon;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/Navbar/NavbarViewModel.cs",
    "content": "﻿using BlazorSample.Domain.Services.Navbar;\n\nnamespace BlazorSample.ViewModels.Navbar;\n\npublic class NavbarViewModel : ViewModelBase\n{\n    private bool _isMenuOpen = true;\n\n    public ObservableCollection<NavbarItemViewModel> NavbarItems { get; }\n\n    public bool IsMenuOpen\n    {\n        get => _isMenuOpen;\n        set => Set(ref _isMenuOpen, value, nameof(IsMenuOpen));\n    }\n\n    public NavbarViewModel(INavbarService navbarService)\n    {\n        NavbarItems = new ObservableCollection<NavbarItemViewModel>(\n            navbarService.NavbarItems.Select(x => new NavbarItemViewModel(x.DisplayName, x.Template!, x.Icon))\n        );\n    }\n\n    public void ToggleMenu()\n    {\n        IsMenuOpen = !IsMenuOpen;\n    }\n\n    private void UpdateActiveItem(NavigationManager navigationManager)\n    {\n        var relativePath = navigationManager.ToBaseRelativePath(navigationManager.Uri);\n\n        foreach (var navbarItem in NavbarItems)\n            if (string.IsNullOrEmpty(relativePath))\n            {\n                navbarItem.IsActive = navbarItem.Template == \"/\";\n            }\n            else\n            {\n                navbarItem.IsActive = navbarItem.Template.StartsWith(\"/\" + relativePath);\n            }\n    }\n\n    public override void OnInitialized()\n    {\n        var navigationManager = RootServiceProvider.GetRequiredService<NavigationManager>();\n        navigationManager.LocationChanged += (_, _) => UpdateActiveItem(navigationManager);\n\n        UpdateActiveItem(navigationManager);\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/ParametersViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic class ParametersViewModel : ViewModelBase\n{\n    private NavigationManager _navigationManager = null!;\n\n    [Parameter] public string? Name { get; set; }\n\n    public string? NewName { get; set; }\n\n    public void NavigateToNewName()\n    {\n        if (string.IsNullOrEmpty(NewName))\n        {\n            return;\n        }\n\n        _navigationManager.NavigateTo($\"/parameters/{NewName}\");\n    }\n\n    public override void OnInitialized()\n    {\n        _navigationManager = RootServiceProvider.GetRequiredService<NavigationManager>();\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/TypedParametersViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic class TypedParametersViewModel : ViewModelBase\n{\n    private NavigationManager _navigationManager = null!;\n\n    [Parameter] public IdType? Id { get; set; }\n\n    public void NavigateToRandomId()\n    {\n        _navigationManager.NavigateTo($\"/typed-parameters/{Guid.NewGuid()}\");\n    }\n\n    public override void OnInitialized()\n    {\n        _navigationManager = RootServiceProvider.GetRequiredService<NavigationManager>();\n    }\n\n    public override void OnParametersSet()\n    {\n        if (Id is null)\n        {\n            NavigateToRandomId();\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/WeatherForecastViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic class WeatherForecastViewModel : ViewModelBase\n{\n    private readonly WeatherForecastEntity _weatherForecastEntity;\n\n    private int _temperatureC;\n\n    private int _temperatureF;\n\n    public DateTime Date => _weatherForecastEntity.Date;\n    public string? Summary => _weatherForecastEntity.Summary;\n\n    public int TemperatureC\n    {\n        get => _temperatureC;\n        set => Set(ref _temperatureC, value, nameof(TemperatureC));\n    }\n\n    public int TemperatureF\n    {\n        get => _temperatureF;\n        set => Set(ref _temperatureF, value, nameof(TemperatureF));\n    }\n\n    public WeatherForecastViewModel(WeatherForecastEntity weatherForecastEntity)\n    {\n        _weatherForecastEntity = weatherForecastEntity;\n        TemperatureC = _weatherForecastEntity.TemperatureC;\n        TemperatureF = _weatherForecastEntity.TemperatureF;\n    }\n}"
  },
  {
    "path": "samples/BlazorSample.ViewModels/WeatherForecastsViewModel.cs",
    "content": "﻿namespace BlazorSample.ViewModels;\n\npublic partial class WeatherForecastsViewModel : ViewModelBase\n{\n    private readonly IWeatherForecastGetter _weatherForecastGetter;\n\n    [Notify] private ObservableCollection<WeatherForecastViewModel>? _forecasts;\n\n    public WeatherForecastsViewModel(IWeatherForecastGetter weatherForecastGetter)\n    {\n        _weatherForecastGetter = weatherForecastGetter;\n    }\n\n    public override async Task OnInitializedAsync()\n    {\n        // Simulate loading time\n        await Task.Delay(1500);\n\n        var forecastData = await _weatherForecastGetter.GetForecasts();\n        Forecasts = new ObservableCollection<WeatherForecastViewModel>(\n            forecastData.Select(x => new WeatherForecastViewModel(x))\n        );\n    }\n\n    public void RandomizeData()\n    {\n        var random = new Random();\n\n        foreach (var weatherForecastEntity in _forecasts!)\n        {\n            weatherForecastEntity.TemperatureC = random.Next(10, 40);\n            weatherForecastEntity.TemperatureF = random.Next(50, 200);\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/App.razor",
    "content": "﻿<Router AppAssembly=\"@typeof(BlazorSample.Components._Imports).Assembly\">\n    <Found Context=\"routeData\">\n        <RouteView RouteData=\"@routeData\" DefaultLayout=\"@typeof(MainLayout)\"/>\n    </Found>\n    <NotFound>\n        <LayoutView Layout=\"@typeof(MainLayout)\">\n            <p>Sorry, there's nothing at this address.</p>\n        </LayoutView>\n    </NotFound>\n</Router>"
  },
  {
    "path": "samples/BlazorServersideSample/BlazorServersideSample.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n    <PropertyGroup>\n        <TargetFramework>net6.0</TargetFramework>\n        <Nullable>enable</Nullable>\n        <ImplicitUsings>true</ImplicitUsings>\n        <IsPackable>false</IsPackable>\n    </PropertyGroup>\n\n    <ItemGroup>\n        <ProjectReference Include=\"..\\..\\src\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\"/>\n        <ProjectReference Include=\"..\\BlazorSample.Components\\BlazorSample.Components.csproj\"/>\n    </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "samples/BlazorServersideSample/Pages/Error.razor",
    "content": "﻿@page \"/error\"\n\n\n<h1 class=\"text-danger\">Error.</h1>\n<h2 class=\"text-danger\">An error occurred while processing your request.</h2>\n\n<h3>Development Mode</h3>\n<p>\n    Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.\n</p>\n<p>\n    <strong>The Development environment shouldn't be enabled for deployed applications.</strong>\n    It can result in displaying sensitive information from exceptions to end users.\n    For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>\n    and restarting the app.\n</p>"
  },
  {
    "path": "samples/BlazorServersideSample/Pages/_Host.cshtml",
    "content": "﻿@page \"/\"\n@namespace BlazorServersideSample.Pages\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\"/>\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n    <title>BlazorServersideSample</title>\n    <base href=\"~/\"/>\n    <link href=\"_content/BlazorSample.Components/site.css\" rel=\"stylesheet\"/>\n    <script src=\"_content/MatBlazor/dist/matBlazor.js\"></script>\n    <link href=\"_content/MatBlazor/dist/matBlazor.css\" rel=\"stylesheet\"/>\n</head>\n<body>\n<app>\n    @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))\n</app>\n\n<script src=\"_framework/blazor.server.js\"></script>\n</body>\n</html>"
  },
  {
    "path": "samples/BlazorServersideSample/Pages/_Imports.razor",
    "content": "﻿@inherits MvvmComponentBase"
  },
  {
    "path": "samples/BlazorServersideSample/Program.cs",
    "content": "namespace BlazorServersideSample;\n\npublic class Program\n{\n    public static void Main(string[] args)\n    {\n        CreateHostBuilder(args).Build().Run();\n    }\n\n    public static IHostBuilder CreateHostBuilder(string[] args)\n    {\n        return Host.CreateDefaultBuilder(args)\n            .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/Properties/launchSettings.json",
    "content": "{\n    \"profiles\": {\n        \"BlazorServersideSample\": {\n            \"commandName\": \"Project\",\n            \"launchBrowser\": true,\n            \"applicationUrl\": \"https://localhost:5001;http://localhost:5000\",\n            \"environmentVariables\": {\n                \"ASPNETCORE_ENVIRONMENT\": \"Development\"\n            }\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/Services/WeatherForecastGetter.cs",
    "content": "using BlazorSample.Domain.Entities;\nusing BlazorSample.Domain.Services;\n\nnamespace BlazorServersideSample.Services;\n\npublic class WeatherForecastGetter : IWeatherForecastGetter\n{\n    private static readonly string[] Summaries =\n    {\n        \"Freezing\", \"Bracing\", \"Chilly\", \"Cool\", \"Mild\", \"Warm\", \"Balmy\", \"Hot\", \"Sweltering\", \"Scorching\"\n    };\n\n    public Task<IEnumerable<WeatherForecastEntity>> GetForecasts()\n    {\n        var rng = new Random();\n        return Task.FromResult(\n            Enumerable.Range(1, 5)\n                .Select(\n                    index => new WeatherForecastEntity\n                    {\n                        Date = DateTime.Now.AddDays(index),\n                        TemperatureC = rng.Next(-20, 55),\n                        Summary = Summaries[rng.Next(Summaries.Length)]\n                    }\n                )\n        );\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/Startup.cs",
    "content": "using BlazorSample.Components.Extensions;\nusing BlazorSample.Domain.Extensions;\nusing BlazorSample.Domain.Services;\nusing BlazorSample.ViewModels.Extensions;\nusing BlazorServersideSample.Services;\n\nnamespace BlazorServersideSample;\n\npublic class Startup\n{\n    public IConfiguration Configuration { get; }\n\n    public Startup(IConfiguration configuration)\n    {\n        Configuration = configuration;\n    }\n\n    // This method gets called by the runtime. Use this method to add services to the container.\n    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940\n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddRazorPages();\n        services.AddServerSideBlazor();\n\n        // Add mvvm to server\n        services.AddMvvm();\n\n        services.AddDomain().AddComponents().AddViewModels();\n        services.AddSingleton<IWeatherForecastGetter, WeatherForecastGetter>();\n    }\n\n    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.\n    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\n    {\n        if (env.IsDevelopment())\n        {\n            app.UseDeveloperExceptionPage();\n        }\n        else\n        {\n            app.UseExceptionHandler(\"/Error\");\n            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.\n            app.UseHsts();\n        }\n\n        app.UseHttpsRedirection();\n        app.UseStaticFiles();\n\n        app.UseRouting();\n\n        app.UseEndpoints(\n            endpoints =>\n            {\n                endpoints.MapBlazorHub();\n                endpoints.MapFallbackToPage(\"/_Host\");\n            }\n        );\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/_Imports.razor",
    "content": "﻿@using System.Net.Http\n@using Microsoft.AspNetCore.Authorization\n@using Microsoft.AspNetCore.Components.Authorization\n@using Microsoft.AspNetCore.Components.Forms\n@using Microsoft.AspNetCore.Components.Routing\n@using Microsoft.AspNetCore.Components.Web\n@using Microsoft.AspNetCore.Components\n@using Microsoft.JSInterop\n@using BlazorServersideSample\n@using MvvmBlazor.Components\n@using BlazorSample.Components.Shared"
  },
  {
    "path": "samples/BlazorServersideSample/appsettings.Development.json",
    "content": "{\n    \"Logging\": {\n        \"LogLevel\": {\n            \"Default\": \"Debug\",\n            \"System\": \"Information\",\n            \"Microsoft\": \"Information\"\n        }\n    }\n}"
  },
  {
    "path": "samples/BlazorServersideSample/appsettings.json",
    "content": "{\n    \"Logging\": {\n        \"LogLevel\": {\n            \"Default\": \"Information\",\n            \"Microsoft\": \"Warning\",\n            \"Microsoft.Hosting.Lifetime\": \"Information\"\n        }\n    },\n    \"AllowedHosts\": \"*\"\n}"
  },
  {
    "path": "src/.editorconfig",
    "content": "[*.{c,c++,cc,cp,cpp,cu,cuh,cxx,h,hh,hpp,hxx,inc,inl,ino,ipp,mpp,proto,tpp}]\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# Microsoft .NET properties\ncsharp_new_line_before_members_in_object_initializers = false\ncsharp_preferred_modifier_order = public, private, protected, internal, new, abstract, virtual, sealed, override, static, readonly, extern, unsafe, volatile, async: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\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:warning\ndotnet_style_qualification_for_field = false:warning\ndotnet_style_qualification_for_method = false:warning\ndotnet_style_qualification_for_property = false:warning\ndotnet_style_require_accessibility_modifiers = for_non_interface_members:hint\n\n# ReSharper properties\nresharper_csharp_empty_block_style = together_same_line\n"
  },
  {
    "path": "src/Directory.Build.props",
    "content": "﻿<Project>\n  <PropertyGroup>\n    <Nullable>enable</Nullable>\n    <ImplicitUsings>enable</ImplicitUsings>\n    <AnalysisMode>All</AnalysisMode>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"IDisposableAnalyzers\" Version=\"4.0.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "src/MvvmBlazor/MvvmBlazor.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net6.0</TargetFramework>\n    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>\n    <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\\GeneratedFiles</CompilerGeneratedFilesOutputPath>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(CI)' == 'true'\">\n    <Deterministic>true</Deterministic>\n    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>\n    <PackageLicenseExpression>MIT</PackageLicenseExpression>\n    <Authors>Christian Klemm</Authors>\n    <Description>A lightweight Blazor Mvvm Library</Description>\n    <PackageProjectUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</PackageProjectUrl>\n    <RepositoryUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <PackageTags>Blazor;Mvvm</PackageTags>\n    <PublishRepositoryUrl>true</PublishRepositoryUrl>\n    <IncludeSymbols>true</IncludeSymbols>\n    <EmbedUntrackedSources>true</EmbedUntrackedSources>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\"/>\n    <ProjectReference Include=\"..\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\"/>\n  </ItemGroup>\n  \n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.1.1\" PrivateAssets=\"All\"/>\n  </ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "src/MvvmBlazor/Properties/AssemblyInfo.cs",
    "content": "﻿[assembly: CLSCompliant(false)]"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/AnalyzerReleases.Shipped.md",
    "content": "﻿## Release 6.0.0\n### New Rules\n\nRule ID | Category | Severity | Notes\n--------|----------|----------|-------\nMVVMBLAZOR001 | MvvmBlazorGenerator | Error | MVVMBLAZOR001_AnalyzerName\nMVVMBLAZOR002 | MvvmBlazorGenerator | Error | MVVMBLAZOR002_AnalyzerName\nMVVMBLAZOR003 | MvvmBlazorGenerator | Error | MVVMBLAZOR003_AnalyzerName\nMVVMBLAZOR004 | MvvmBlazorGenerator | Error | MVVMBLAZOR004_AnalyzerName\n\n## Release 6.0.2\n### New Rules\n\nRule ID | Category | Severity | Notes\n--------|----------|----------|-------\nMVVMBLAZOR005 | MvvmBlazorGenerator | Error | MVVMBLAZOR005_AnalyzerName"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/AnalyzerReleases.Unshipped.md",
    "content": "﻿"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Components/MvvmComponentClassContext.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.Components;\n\ninternal class MvvmComponentClassContext\n{\n    public ClassDeclarationSyntax ComponentClass { get; }\n    public INamedTypeSymbol ComponentSymbol { get; }\n\n    public MvvmComponentClassContext(ClassDeclarationSyntax componentClass, INamedTypeSymbol componentSymbol)\n    {\n        ComponentClass = componentClass;\n        ComponentSymbol = componentSymbol;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Components/MvvmComponentGenerator.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.Components;\n\n[Generator]\npublic class MvvmComponentGenerator : ISourceGenerator\n{\n    private static readonly DiagnosticDescriptor ComponentNotPartialError = new(\n        \"MVVMBLAZOR001\",\n        \"Component needs to be partial\",\n        \"Mvvm Component class '{0}' needs to be partial\",\n        \"MvvmBlazorGenerator\",\n        DiagnosticSeverity.Error,\n        true\n    );\n\n    private static readonly DiagnosticDescriptor ComponentWrongBaseClassError = new(\n        \"MVVMBLAZOR002\",\n        \"Missing component base class\",\n        \"Mvvm Component class '{0}' needs to be assignable to '{1}'\",\n        \"MvvmBlazorGenerator\",\n        DiagnosticSeverity.Error,\n        true\n    );\n\n    private static readonly DiagnosticDescriptor ComponentWrongTypeParameterError = new(\n        \"MVVMBLAZOR005\",\n        \"Wrong type parameter\",\n        \"Mvvm Component class '{0}' needs to have exactly one type parameter named '{1}'\",\n        \"MvvmBlazorGenerator\",\n        DiagnosticSeverity.Error,\n        true\n    );\n\n\n    public void Execute(GeneratorExecutionContext context)\n    {\n        if (context.SyntaxContextReceiver is not MvvmComponentSyntaxReceiver syntaxReceiver ||\n            syntaxReceiver.ComponentClassContexts.Count == 0)\n        {\n            return;\n        }\n\n        foreach (var componentClassContext in syntaxReceiver.ComponentClassContexts)\n            ProcessComponent(context, componentClassContext);\n    }\n\n    public void Initialize(GeneratorInitializationContext context)\n    {\n        context.RegisterForSyntaxNotifications(() => new MvvmComponentSyntaxReceiver());\n    }\n\n    private static void ProcessComponent(\n        GeneratorExecutionContext context,\n        MvvmComponentClassContext componentClassContext)\n    {\n        var componentClass = componentClassContext.ComponentClass;\n        var isPartial = componentClass.Modifiers.Any(SyntaxKind.PartialKeyword);\n        if (!isPartial)\n        {\n            context.ReportDiagnostic(\n                Diagnostic.Create(\n                    ComponentNotPartialError,\n                    Location.Create(\n                        componentClass.SyntaxTree,\n                        TextSpan.FromBounds(componentClass.SpanStart, componentClass.SpanStart)\n                    ),\n                    componentClass.Identifier\n                )\n            );\n            return;\n        }\n\n        var componentBaseType =\n            context.Compilation.GetTypeByMetadataName(\"Microsoft.AspNetCore.Components.ComponentBase\")!;\n        if (!componentClassContext.ComponentSymbol.InheritsFrom(componentBaseType))\n        {\n            context.ReportDiagnostic(\n                Diagnostic.Create(\n                    ComponentWrongBaseClassError,\n                    Location.Create(\n                        componentClass.SyntaxTree,\n                        TextSpan.FromBounds(componentClass.SpanStart, componentClass.SpanStart)\n                    ),\n                    componentClass.Identifier,\n                    componentBaseType.GetMetadataName()\n                )\n            );\n            return;\n        }\n\n        if (componentClass.TypeParameterList is null || componentClass.TypeParameterList.Parameters.Count == 0)\n        {\n            AddComponent(context, componentClassContext, componentClass);\n            return;\n        }\n\n        AddGenericComponent(context, componentClassContext, componentClass);\n    }\n\n    private static void AddComponent(\n        GeneratorExecutionContext context,\n        MvvmComponentClassContext componentClassContext,\n        BaseTypeDeclarationSyntax componentClass)\n    {\n        var componentSourceText = SourceText.From(GenerateComponentCode(componentClassContext), Encoding.UTF8);\n        context.AddSource(componentClass.Identifier + \".g.cs\", componentSourceText);\n    }\n\n    private static void AddGenericComponent(\n        GeneratorExecutionContext context,\n        MvvmComponentClassContext componentClassContext,\n        TypeDeclarationSyntax componentClass)\n    {\n        const string typeParameterName = \"T\";\n        var genericComponentSourceText = SourceText.From(\n            GenerateGenericComponentCode(componentClassContext, typeParameterName),\n            Encoding.UTF8\n        );\n\n        var typeParameterList = componentClass.TypeParameterList;\n        if (typeParameterList is null || typeParameterList.Parameters.Count != 1 || typeParameterList.Parameters[0].Identifier.ValueText != typeParameterName)\n        {\n            context.ReportDiagnostic(\n                Diagnostic.Create(\n                    ComponentWrongTypeParameterError,\n                    Location.Create(\n                        componentClass.SyntaxTree,\n                        TextSpan.FromBounds(componentClass.SpanStart, componentClass.SpanStart)\n                    ),\n                    componentClass.Identifier,\n                    typeParameterName\n                )\n            );\n        }\n\n        context.AddSource(componentClass.Identifier + \"T.g.cs\", genericComponentSourceText);\n    }\n\n    private static string GenerateComponentCode(MvvmComponentClassContext componentClassContext)\n    {\n        var componentNamespace = componentClassContext.ComponentSymbol.ContainingNamespace;\n        var componentClassName = componentClassContext.ComponentClass.Identifier;\n\n        return $@\"\n#nullable enable\nusing System;\nusing System.Linq.Expressions;\nusing Microsoft.AspNetCore.Components;\nusing Microsoft.Extensions.DependencyInjection;\nusing MvvmBlazor.Components;\nusing MvvmBlazor.ViewModel;\n\nnamespace {componentNamespace}\n{{\n    partial class {componentClassName} : IDisposable, IAsyncDisposable\n    {{\n        private AsyncServiceScope? _scope;\n\n        [Inject] IServiceScopeFactory ScopeFactory {{ get; set; }} = default!;\n        [Inject] protected IServiceProvider RootServiceProvider {{ get; set; }} = default!;\n        protected bool IsDisposed {{ get; private set; }}\n\n        public MvvmBlazor.Internal.Bindings.IBinder Binder {{ get; private set; }} = null!;\n\n#pragma warning disable CS0109\n        protected new IServiceProvider ScopedServices\n#pragma warning restore CS0109\n        {{\n            get\n            {{\n                if (ScopeFactory == null)\n                {{\n                    throw new InvalidOperationException(\"\"Services cannot be accessed before the component is initialized.\"\");\n                }}\n\n                if (IsDisposed)\n                {{\n                    throw new ObjectDisposedException(GetType().Name);\n                }}\n\n                _scope ??= ScopeFactory.CreateAsyncScope();\n                return _scope.Value.ServiceProvider;\n            }}\n        }}\n\n#pragma warning disable CS8618\n        protected internal {componentClassName}(IServiceProvider services)\n#pragma warning restore CS8618\n        {{\n            RootServiceProvider = services;\n            ScopeFactory = services.GetRequiredService<IServiceScopeFactory>();\n            InitializeDependencies();\n        }}\n\n#pragma warning disable CS8618\n        protected {componentClassName}()\n#pragma warning restore CS8618\n        {{\n        }}\n\n        private void InitializeDependencies()\n        {{\n            Binder = ScopedServices.GetRequiredService<MvvmBlazor.Internal.Bindings.IBinder>();\n            Binder.ValueChangedCallback = BindingOnBindingValueChanged;\n        }}\n\n        protected internal TValue Bind<TViewModel, TValue>(TViewModel viewModel,\n            Expression<Func<TViewModel, TValue>> property)\n            where TViewModel : ViewModelBase\n        {{\n            return AddBinding(viewModel, property);\n        }}\n\n        public virtual TValue AddBinding<TViewModel, TValue>(TViewModel viewModel,\n            Expression<Func<TViewModel, TValue>> propertyExpression) where TViewModel : ViewModelBase\n        {{\n            return Binder.Bind(viewModel, propertyExpression);\n        }}\n\n        protected override void OnInitialized()\n        {{\n            base.OnInitialized();\n            InitializeDependencies();\n        }}\n\n        internal virtual void BindingOnBindingValueChanged(object sender, EventArgs e)\n        {{\n            InvokeAsync(StateHasChanged);\n        }}\n\n        public void Dispose()\n        {{\n            if (!IsDisposed)\n            {{\n                _scope?.Dispose();\n                _scope = null;\n                Dispose(true);\n                GC.SuppressFinalize(this);\n                IsDisposed = true;\n            }}\n        }}\n\n        protected virtual void Dispose(bool disposing)\n        {{\n        }}\n\n        public async ValueTask DisposeAsync()\n        {{\n            if (!IsDisposed)\n            {{\n                if (_scope is not null)\n                {{\n                    await _scope.Value.DisposeAsync();\n                    _scope = null;\n                }}\n\n                await DisposeAsyncCore();\n                Dispose(false);\n                GC.SuppressFinalize(this);\n                IsDisposed = true;\n            }}\n        }}\n\n        protected virtual ValueTask DisposeAsyncCore()\n        {{\n            return ValueTask.CompletedTask;\n        }}\n    }}\n}}\n            \";\n    }\n\n    private static string GenerateGenericComponentCode(MvvmComponentClassContext componentClassContext, string typeParameterName)\n    {\n        var componentNamespace = componentClassContext.ComponentSymbol.ContainingNamespace;\n        var componentClassName = componentClassContext.ComponentClass.Identifier;\n\n        return $@\"\n#nullable enable\nusing System;\nusing System.Linq.Expressions;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Components;\nusing Microsoft.Extensions.DependencyInjection;\nusing MvvmBlazor.Internal.Parameters;\nusing MvvmBlazor.ViewModel;\n\nnamespace {componentNamespace}\n{{\n    partial class {componentClassName}<{typeParameterName}>\n        where T : ViewModelBase\n    {{\n        private MvvmBlazor.Internal.Parameters.IViewModelParameterSetter? _viewModelParameterSetter;\n\n#pragma warning disable CS8618\n        protected internal {componentClassName}(IServiceProvider serviceProvider) : base(serviceProvider)\n#pragma warning restore CS8618\n        {{\n            SetBindingContext();\n        }}\n\n#pragma warning disable CS8618\n        protected {componentClassName}()\n#pragma warning restore CS8618\n        {{\n        }}\n\n        protected T BindingContext {{ get; set; }}\n\n        private void SetBindingContext()\n        {{\n            BindingContext ??= ScopedServices.GetRequiredService<T>();\n            BindingContext.RootServiceProvider = RootServiceProvider;\n        }}\n\n        private void SetParameters()\n        {{\n            if (IsDisposed)\n                return;\n\n            if (BindingContext is null)\n                throw new InvalidOperationException($\"\"{{nameof(BindingContext)}} is not set\"\");\n\n            _viewModelParameterSetter ??= ScopedServices.GetRequiredService<MvvmBlazor.Internal.Parameters.IViewModelParameterSetter>();\n            _viewModelParameterSetter.ResolveAndSet(this, BindingContext);\n        }}\n\n        protected internal TValue Bind<TValue>(Expression<Func<T, TValue>> property)\n        {{\n            if (BindingContext is null)\n                throw new InvalidOperationException($\"\"{{nameof(BindingContext)}} is not set\"\");\n\n            return AddBinding(BindingContext, property);\n        }}\n\n        /// <inheritdoc />\n        protected override void OnInitialized()\n        {{\n            SetBindingContext();\n            base.OnInitialized();\n            BindingContext?.OnInitialized();\n        }}\n\n        /// <inheritdoc />\n        protected override async Task OnInitializedAsync()\n        {{\n            await base.OnInitializedAsync();\n            await BindingContext!.OnInitializedAsync();\n        }}\n\n        /// <inheritdoc />\n        protected override void OnParametersSet()\n        {{\n            SetParameters();\n            base.OnParametersSet();\n            BindingContext?.OnParametersSet();\n        }}\n\n        /// <inheritdoc />\n        protected override async Task OnParametersSetAsync()\n        {{\n            await base.OnParametersSetAsync();\n            await BindingContext.OnParametersSetAsync();\n        }}\n\n        /// <inheritdoc />\n        protected override bool ShouldRender()\n        {{\n            return BindingContext!.ShouldRender();\n        }}\n\n        /// <inheritdoc />\n        protected override void OnAfterRender(bool firstRender)\n        {{\n            base.OnAfterRender(firstRender);\n            BindingContext!.OnAfterRender(firstRender);\n        }}\n\n        /// <inheritdoc />\n        protected override async Task OnAfterRenderAsync(bool firstRender)\n        {{\n            await base.OnAfterRenderAsync(firstRender);\n            await BindingContext!.OnAfterRenderAsync(firstRender);\n        }}\n\n        /// <inheritdoc />\n        public override async Task SetParametersAsync(ParameterView parameters)\n        {{\n            await base.SetParametersAsync(parameters);\n\n            if (BindingContext != null)\n            {{\n                await BindingContext.SetParametersAsync(parameters);\n            }}\n        }}\n    }}\n}}\n            \";\n    }\n}\n"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Components/MvvmComponentSyntaxReceiver.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.Components;\n\ninternal class MvvmComponentSyntaxReceiver : ISyntaxContextReceiver\n{\n    public List<MvvmComponentClassContext> ComponentClassContexts { get; } = new();\n\n    public void OnVisitSyntaxNode(GeneratorSyntaxContext context)\n    {\n        if (context.Node is not ClassDeclarationSyntax cds || cds.AttributeLists.Count == 0)\n        {\n            return;\n        }\n\n        var symbol = context.SemanticModel.GetDeclaredSymbol(context.Node);\n        if (symbol is not INamedTypeSymbol typeSymbol)\n        {\n            return;\n        }\n\n        var isDecoratedWithAttribute = typeSymbol.GetAttributes()\n            .Any(ad => ad.AttributeClass is { Name: \"MvvmComponentAttribute\" });\n        if (!isDecoratedWithAttribute)\n        {\n            return;\n        }\n\n        ComponentClassContexts.Add(new MvvmComponentClassContext(cds, typeSymbol));\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Extensions/StringBuilderExtensions.cs",
    "content": "﻿using System.Globalization;\n\nnamespace MvvmBlazor.CodeGenerators.Extensions;\n\ninternal static class StringBuilderExtensions\n{\n    public static void AppendLineFormat(this StringBuilder stringBuilder, string format, object arg0)\n    {\n        stringBuilder.AppendFormat(CultureInfo.InvariantCulture, format, arg0);\n        stringBuilder.AppendLine();\n    }\n\n    public static void AppendLineFormat(this StringBuilder stringBuilder, string format, object arg0, object arg1)\n    {\n        stringBuilder.AppendFormat(CultureInfo.InvariantCulture, format, arg0, arg1);\n        stringBuilder.AppendLine();\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Extensions/SymbolExtensions.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.Extensions;\n\ninternal static class SymbolExtensions\n{\n    public static string GetMetadataName(this ISymbol symbol)\n    {\n        return string.Join(\".\", symbol.ContainingNamespace, symbol.MetadataName);\n    }\n\n    public static bool InheritsFrom(this ITypeSymbol symbol, ISymbol baseType)\n    {\n        if (symbol.BaseType is null)\n        {\n            return false;\n        }\n\n        if (symbol.BaseType.GetMetadataName() == baseType.GetMetadataName())\n        {\n            return true;\n        }\n\n        return symbol.BaseType.InheritsFrom(baseType);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/GlobalUsings.cs",
    "content": "﻿global using System.Text;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.CodeAnalysis.CSharp;\nglobal using Microsoft.CodeAnalysis.CSharp.Syntax;\nglobal using Microsoft.CodeAnalysis.Text;\nglobal using MvvmBlazor.CodeGenerators.Extensions;\nglobal using System.Collections.Generic;\nglobal using System.Linq;"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/MvvmBlazor.CodeGenerators.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n    <LangVersion>10.0</LangVersion>\n    <IncludeBuildOutput>false</IncludeBuildOutput>\n    <IncludeSymbols>false</IncludeSymbols>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(CI)' == 'true'\">\n    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>\n    <PackageLicenseExpression>MIT</PackageLicenseExpression>\n    <Authors>Christian Klemm</Authors>\n    <Description>Code generators for a lightweight Blazor Mvvm Library</Description>\n    <PackageProjectUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</PackageProjectUrl>\n    <RepositoryUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <PackageTags>Blazor;Mvvm</PackageTags>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.CodeAnalysis.Analyzers\" Version=\"3.3.3\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.CodeAnalysis.CSharp\" Version=\"4.0.1\"/>\n  </ItemGroup>\n\n  <ItemGroup>\n    <!-- Package the generator in the analyzer directory of the nuget package -->\n    <None Include=\"$(OutputPath)\\$(AssemblyName).dll\" Pack=\"true\" PackagePath=\"analyzers/dotnet/cs\" Visible=\"false\"/>\n  </ItemGroup>\n</Project>\n"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/NotifyPropertyChanged/NotifyPropertyChangedContext.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.NotifyPropertyChanged;\n\ninternal class NotifyPropertyChangedContext\n{\n    public FieldDeclarationSyntax Field { get; }\n    public IFieldSymbol FieldSymbol { get; }\n\n    public NotifyPropertyChangedContext(FieldDeclarationSyntax field, IFieldSymbol fieldSymbol)\n    {\n        Field = field;\n        FieldSymbol = fieldSymbol;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/NotifyPropertyChanged/NotifyPropertyChangedGenerator.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.NotifyPropertyChanged;\n\n[Generator]\npublic class NotifyPropertyChangedGenerator : ISourceGenerator\n{\n    private static readonly DiagnosticDescriptor ViewModelNotPartialError = new(\n        \"MVVMBLAZOR003\",\n        \"View model needs to be partial\",\n        \"View model class '{0}' needs to be partial\",\n        \"MvvmBlazorGenerator\",\n        DiagnosticSeverity.Error,\n        true\n    );\n\n    private static readonly DiagnosticDescriptor ViewModelMissingBaseClass = new(\n        \"MVVMBLAZOR004\",\n        \"Missing view model base class\",\n        \"View model class '{0}' needs to be assignable to '{1}'\",\n        \"MvvmBlazorGenerator\",\n        DiagnosticSeverity.Error,\n        true\n    );\n\n    public void Initialize(GeneratorInitializationContext context)\n    {\n        context.RegisterForSyntaxNotifications(() => new NotifyPropertyChangedSyntaxReceiver());\n    }\n\n    public void Execute(GeneratorExecutionContext context)\n    {\n        if (context.SyntaxContextReceiver is not NotifyPropertyChangedSyntaxReceiver syntaxReceiver ||\n            syntaxReceiver.Contexts.Count == 0)\n        {\n            return;\n        }\n\n        foreach (var fieldContexts in syntaxReceiver.Contexts) ProcessViewModel(context, fieldContexts.Value);\n    }\n\n    private static void ProcessViewModel(\n        GeneratorExecutionContext context,\n        IReadOnlyCollection<NotifyPropertyChangedContext> fieldContexts)\n    {\n        var viewModelClass = fieldContexts.First().Field.Ancestors().OfType<ClassDeclarationSyntax>().First();\n        var isPartial = viewModelClass.Modifiers.Any(SyntaxKind.PartialKeyword);\n        if (!isPartial)\n        {\n            context.ReportDiagnostic(\n                Diagnostic.Create(\n                    ViewModelNotPartialError,\n                    Location.Create(\n                        viewModelClass.SyntaxTree,\n                        TextSpan.FromBounds(viewModelClass.SpanStart, viewModelClass.SpanStart)\n                    ),\n                    viewModelClass.Identifier\n                )\n            );\n            return;\n        }\n\n        var viewModelType = fieldContexts.First().FieldSymbol.ContainingType;\n        var viewModelBaseType = context.Compilation.GetTypeByMetadataName(\"MvvmBlazor.ViewModel.ViewModelBase\")!;\n        if (!viewModelType.InheritsFrom(viewModelBaseType))\n        {\n            context.ReportDiagnostic(\n                Diagnostic.Create(\n                    ViewModelMissingBaseClass,\n                    Location.Create(\n                        viewModelClass.SyntaxTree,\n                        TextSpan.FromBounds(viewModelClass.SpanStart, viewModelClass.SpanStart)\n                    ),\n                    viewModelClass.Identifier\n                )\n            );\n            return;\n        }\n\n        AddViewModel(context, fieldContexts, viewModelType, viewModelClass);\n    }\n\n    private static void AddViewModel(\n        GeneratorExecutionContext context,\n        IReadOnlyCollection<NotifyPropertyChangedContext> fieldContexts,\n        INamedTypeSymbol viewModelType,\n        ClassDeclarationSyntax viewModelClass)\n    {\n        var viewModelSourceText = SourceText.From(\n            GenerateViewModelCode(fieldContexts, viewModelType, viewModelClass),\n            Encoding.UTF8\n        );\n        context.AddSource(viewModelClass.Identifier + \".Generated.cs\", viewModelSourceText);\n    }\n\n    private static string GenerateViewModelCode(\n        IReadOnlyCollection<NotifyPropertyChangedContext> fieldContexts,\n        INamedTypeSymbol viewModelType,\n        ClassDeclarationSyntax viewModelClass)\n    {\n        var viewModelNamespace = viewModelType.ContainingNamespace;\n        var viewModelClassName = viewModelClass.Identifier;\n\n        var genericArgumentString = string.Empty;\n        var genericArguments = viewModelType.TypeArguments.Select(x => x.Name).ToList();\n        if (genericArguments.Count > 0)\n        {\n            genericArgumentString = \"<\" + string.Join(\", \", genericArguments) + \">\";\n        }\n\n        var sb = new StringBuilder();\n\n        sb.AppendLine(\"#nullable enable\");\n        sb.AppendLine();\n        sb.AppendLineFormat(\"namespace {0}\", viewModelNamespace);\n        sb.AppendLine(\"{\");\n        sb.AppendLineFormat(\"    partial class {0}{1}\", viewModelClassName, genericArgumentString);\n        sb.AppendLine(\"    {\");\n\n        foreach (var fieldContext in fieldContexts)\n        {\n            var propertyType = fieldContext.FieldSymbol.Type;\n            var fieldName = fieldContext.FieldSymbol.Name;\n            var propertyName = GetPropertyName(fieldName);\n            sb.AppendLineFormat(\"        public {0} {1}\", propertyType, propertyName);\n            sb.AppendLine(\"        {\");\n            sb.AppendLineFormat(\"            get => {0};\", fieldName);\n            sb.AppendLineFormat(\"            set => Set(ref {0}, value, \\\"{1}\\\");\", fieldName, propertyName);\n            sb.AppendLine(\"        }\");\n        }\n\n        sb.AppendLine(\"    }\");\n        sb.AppendLine(\"}\");\n\n        return sb.ToString();\n    }\n\n    private static string GetPropertyName(string fieldName)\n    {\n        var fieldNameWithoutUnderscore = fieldName.TrimStart('_');\n        var firstChar = fieldNameWithoutUnderscore.Substring(0, 1);\n\n        return firstChar.ToUpperInvariant() + fieldNameWithoutUnderscore.Substring(1);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/NotifyPropertyChanged/NotifyPropertyChangedSyntaxReceiver.cs",
    "content": "﻿namespace MvvmBlazor.CodeGenerators.NotifyPropertyChanged;\n\ninternal class NotifyPropertyChangedSyntaxReceiver : ISyntaxContextReceiver\n{\n    public Dictionary<string, List<NotifyPropertyChangedContext>> Contexts { get; } = new();\n\n    public void OnVisitSyntaxNode(GeneratorSyntaxContext context)\n    {\n        if (context.Node is not FieldDeclarationSyntax fds || fds.AttributeLists.Count == 0)\n        {\n            return;\n        }\n\n        foreach (var variable in fds.Declaration.Variables)\n        {\n            var symbol = context.SemanticModel.GetDeclaredSymbol(variable);\n            if (symbol is not IFieldSymbol fieldSymbol)\n            {\n                continue;\n            }\n\n            var isDecoratedWithAttribute = fieldSymbol.GetAttributes()\n                .Any(ad => ad.AttributeClass is { Name: \"NotifyAttribute\" });\n            if (!isDecoratedWithAttribute)\n            {\n                return;\n            }\n\n            var className = fieldSymbol.ContainingType.Name;\n\n            if (!Contexts.TryGetValue(className, out var fields))\n            {\n                fields = new List<NotifyPropertyChangedContext>();\n                Contexts.Add(className, fields);\n            }\n\n            fields.Add(new NotifyPropertyChangedContext(fds, fieldSymbol));\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.CodeGenerators/Properties/AssemblyInfo.cs",
    "content": "﻿[assembly: CLSCompliant(false)]"
  },
  {
    "path": "src/MvvmBlazor.Core/Components/MvvmComponentAttribute.cs",
    "content": "﻿// ReSharper disable once CheckNamespace\n\nnamespace MvvmBlazor;\n\n[AttributeUsage(AttributeTargets.Class)]\npublic sealed class MvvmComponentAttribute : Attribute { }"
  },
  {
    "path": "src/MvvmBlazor.Core/Components/MvvmComponentBase.cs",
    "content": "﻿namespace MvvmBlazor.Components;\n\n[MvvmComponent]\n// ReSharper disable once PartialTypeWithSinglePart\npublic abstract partial class MvvmComponentBase : ComponentBase { }"
  },
  {
    "path": "src/MvvmBlazor.Core/Components/MvvmComponentBaseT.cs",
    "content": "﻿namespace MvvmBlazor.Components;\n\n[MvvmComponent]\n// ReSharper disable once PartialTypeWithSinglePart\npublic abstract partial class MvvmComponentBase<T> : MvvmComponentBase where T : ViewModelBase { }"
  },
  {
    "path": "src/MvvmBlazor.Core/Extensions/ServiceCollectionExtensions.cs",
    "content": "﻿using Binder = MvvmBlazor.Internal.Bindings.Binder;\n\n// ReSharper disable once CheckNamespace\nnamespace Microsoft.Extensions.DependencyInjection;\n\npublic static class ServiceCollectionExtensions\n{\n    public static IServiceCollection AddMvvm(this IServiceCollection serviceCollection)\n    {\n        serviceCollection.AddSingleton<IBindingFactory, BindingFactory>();\n        serviceCollection.AddSingleton<IParameterResolver, ParameterResolver>();\n        serviceCollection.AddSingleton<IParameterCache, ParameterCache>();\n        serviceCollection.AddSingleton<IViewModelParameterSetter, ViewModelParameterSetter>();\n        serviceCollection.AddTransient<IWeakEventManager, WeakEventManager>();\n        serviceCollection.AddTransient<IBinder, Binder>();\n\n        return serviceCollection;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/GlobalUsings.cs",
    "content": "﻿global using System.ComponentModel;\nglobal using System.Linq.Expressions;\nglobal using System.Reflection;\nglobal using System.Runtime.CompilerServices;\nglobal using Microsoft.AspNetCore.Components;\nglobal using MvvmBlazor.Internal.Bindings;\nglobal using System.Collections.Specialized;\nglobal using MvvmBlazor.Internal.WeakEventListener;\nglobal using System.Runtime.Serialization;\nglobal using MvvmBlazor.ViewModel;\nglobal using MvvmBlazor.Components;\nglobal using MvvmBlazor.Internal.Parameters;"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Bindings/Binder.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Bindings;\n\npublic interface IBinder\n{\n    Action<IBinding, EventArgs>? ValueChangedCallback { get; set; }\n\n    TValue Bind<TViewModel, TValue>(TViewModel viewModel, Expression<Func<TViewModel, TValue>> propertyExpression)\n        where TViewModel : ViewModelBase;\n}\n\ninternal class Binder : IBinder, IDisposable\n{\n    private readonly IBindingFactory _bindingFactory;\n    private readonly HashSet<IBinding> _bindings = new();\n    private readonly IWeakEventManager _weakEventManager;\n    private bool _isDisposed;\n\n    public Binder(IBindingFactory bindingFactory, IWeakEventManager weakEventManager)\n    {\n        _bindingFactory = bindingFactory;\n        _weakEventManager = weakEventManager;\n    }\n\n    public Action<IBinding, EventArgs>? ValueChangedCallback { get; set; }\n\n    public TValue Bind<TViewModel, TValue>(\n        TViewModel viewModel,\n        Expression<Func<TViewModel, TValue>> propertyExpression) where TViewModel : ViewModelBase\n    {\n        ThrowIfDisposed();\n\n        if (ValueChangedCallback is null)\n        {\n            throw new BindingException($\"{nameof(ValueChangedCallback)} is null\");\n        }\n\n        var propertyInfo = ValidateAndResolveBindingContext(viewModel, propertyExpression);\n\n        var binding = _bindingFactory.Create(viewModel, propertyInfo, _weakEventManager);\n        if (_bindings.Contains(binding))\n        {\n            return (TValue)binding.GetValue();\n        }\n\n        _weakEventManager.AddWeakEventListener(binding, nameof(Binding.BindingValueChanged), ValueChangedCallback);\n        binding.Initialize();\n\n        _bindings.Add(binding);\n\n        return (TValue)binding.GetValue();\n    }\n\n    protected static PropertyInfo ValidateAndResolveBindingContext<TViewModel, TValue>(\n        TViewModel viewModel,\n        Expression<Func<TViewModel, TValue>> property) where TViewModel : ViewModelBase\n    {\n        if (viewModel is null)\n        {\n            throw new BindingException(\"ViewModelType is null\");\n        }\n\n        if (property is null)\n        {\n            throw new BindingException(\"Property expression is null\");\n        }\n\n        if (property.Body is not MemberExpression { Member: PropertyInfo p })\n        {\n            throw new BindingException(\"Binding member needs to be a property\");\n        }\n\n        if (typeof(TViewModel).GetProperty(p.Name) is null)\n        {\n            throw new BindingException($\"Cannot find property {p.Name} in type {viewModel.GetType().FullName}\");\n        }\n\n        return p;\n    }\n\n    #region IDisposable\n\n    public void Dispose()\n    {\n        Dispose(true);\n        GC.SuppressFinalize(this);\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            ThrowIfDisposed();\n\n            _isDisposed = true;\n            DisposeBindings();\n        }\n    }\n\n    private void DisposeBindings()\n    {\n        foreach (var binding in _bindings)\n        {\n            _weakEventManager.RemoveWeakEventListener(binding);\n            binding.Dispose();\n        }\n    }\n\n    private void ThrowIfDisposed()\n    {\n        if (_isDisposed)\n        {\n            throw new ObjectDisposedException(nameof(Binder));\n        }\n    }\n\n    ~Binder()\n    {\n        Dispose(false);\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Bindings/Binding.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Bindings;\n\npublic interface IBinding : IDisposable\n{\n    INotifyPropertyChanged Source { get; }\n    PropertyInfo PropertyInfo { get; }\n    event EventHandler? BindingValueChanged;\n    void Initialize();\n    object GetValue();\n}\n\ninternal class Binding : IBinding\n{\n    private readonly IWeakEventManager _weakEventManager;\n    private INotifyCollectionChanged? _boundCollection;\n    private bool _isCollection;\n\n    public Binding(INotifyPropertyChanged source, PropertyInfo propertyInfo, IWeakEventManager weakEventManager)\n    {\n        _weakEventManager = weakEventManager;\n        Source = source;\n        PropertyInfo = propertyInfo;\n    }\n\n    public INotifyPropertyChanged Source { get; }\n    public PropertyInfo PropertyInfo { get; }\n\n    public event EventHandler? BindingValueChanged;\n\n    public void Initialize()\n    {\n        _isCollection = typeof(INotifyCollectionChanged).IsAssignableFrom(PropertyInfo.PropertyType);\n        _weakEventManager.AddWeakEventListener(Source, SourceOnPropertyChanged);\n        AddCollectionBindings();\n    }\n\n    public object GetValue()\n    {\n        return PropertyInfo.GetValue(Source, null)!;\n    }\n\n    private void AddCollectionBindings()\n    {\n        if (!_isCollection || GetValue() is not INotifyCollectionChanged collection)\n        {\n            return;\n        }\n\n        _weakEventManager.AddWeakEventListener(collection, CollectionOnCollectionChanged);\n        _boundCollection = collection;\n    }\n\n    private void SourceOnPropertyChanged(object sender, PropertyChangedEventArgs e)\n    {\n        if (e.PropertyName is null)\n        {\n            BindingValueChanged?.Invoke(this, EventArgs.Empty);\n            return;\n        }\n\n        // This should just listen to the bindings property\n        if (e.PropertyName != PropertyInfo.Name)\n        {\n            return;\n        }\n\n        if (_isCollection)\n        {\n            // If our binding is a collection binding we need to remove the event\n            // and reinitialize the collection bindings\n            if (_boundCollection != null)\n            {\n                _weakEventManager.RemoveWeakEventListener(_boundCollection);\n            }\n\n            AddCollectionBindings();\n        }\n\n\n        BindingValueChanged?.Invoke(this, EventArgs.Empty);\n    }\n\n    private void CollectionOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)\n    {\n        BindingValueChanged?.Invoke(this, EventArgs.Empty);\n    }\n\n    #region IDisposable Support\n\n    public void Dispose()\n    {\n        Dispose(true);\n        GC.SuppressFinalize(this);\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            if (_boundCollection != null)\n            {\n                _weakEventManager.RemoveWeakEventListener(_boundCollection);\n            }\n\n            _weakEventManager.RemoveWeakEventListener(Source);\n        }\n    }\n\n    #endregion\n\n    #region Base overrides\n\n    public override string ToString()\n    {\n        return $\"{PropertyInfo?.DeclaringType?.Name}.{PropertyInfo?.Name}\";\n    }\n\n    public override bool Equals(object? obj)\n    {\n        return obj is Binding b && ReferenceEquals(b.Source, Source) && b.PropertyInfo.Name == PropertyInfo.Name;\n    }\n\n    public override int GetHashCode()\n    {\n        var hash = 13;\n        hash = hash * 7 + Source.GetHashCode();\n        hash = hash * 7 + PropertyInfo.Name.GetHashCode(StringComparison.InvariantCulture);\n\n        return hash;\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Bindings/BindingException.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Bindings;\n\npublic class BindingException : Exception\n{\n    public BindingException() { }\n\n    protected BindingException(SerializationInfo info, StreamingContext context) : base(info, context) { }\n\n    public BindingException(string message) : base(message) { }\n\n    public BindingException(string message, Exception innerException) : base(message, innerException) { }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Bindings/BindingFactory.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Bindings;\n\ninternal interface IBindingFactory\n{\n    IBinding Create(INotifyPropertyChanged source, PropertyInfo propertyInfo, IWeakEventManager weakEventManager);\n}\n\ninternal class BindingFactory : IBindingFactory\n{\n    public IBinding Create(INotifyPropertyChanged source, PropertyInfo propertyInfo, IWeakEventManager weakEventManager)\n    {\n        return new Binding(source, propertyInfo, weakEventManager);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Parameters/ParameterCache.cs",
    "content": "﻿using System.Collections.Concurrent;\n\nnamespace MvvmBlazor.Internal.Parameters;\n\ninternal interface IParameterCache\n{\n    ParameterInfo? Get(Type type);\n    void Set(Type type, ParameterInfo info);\n}\n\ninternal class ParameterCache : IParameterCache\n{\n    private readonly ConcurrentDictionary<Type, ParameterInfo> _cache = new();\n\n    public ParameterInfo? Get(Type type)\n    {\n        return _cache.TryGetValue(type, out var info) ? info : null;\n    }\n\n    public void Set(Type type, ParameterInfo info)\n    {\n        ArgumentNullException.ThrowIfNull(info);\n        _cache[type] = info;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Parameters/ParameterException.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Parameters;\n\n[Serializable]\npublic class ParameterException : Exception\n{\n    public ParameterException() { }\n    protected ParameterException(SerializationInfo info, StreamingContext context) : base(info, context) { }\n    public ParameterException(string? message) : base(message) { }\n    public ParameterException(string? message, Exception? innerException) : base(message, innerException) { }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Parameters/ParameterInfo.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Parameters;\n\ninternal record ParameterInfo\n{\n    private readonly Dictionary<PropertyInfo, PropertyInfo> _parameters = new();\n\n    public IReadOnlyDictionary<PropertyInfo, PropertyInfo> Parameters => _parameters;\n\n    public ParameterInfo(IEnumerable<PropertyInfo> componentProperties, IEnumerable<PropertyInfo> viewModelProperties)\n    {\n        var componentPropertyDict = componentProperties.ToDictionary(x => x.Name);\n        foreach (var viewModelProperty in viewModelProperties.OrderBy(x => x.Name))\n        {\n            if (!componentPropertyDict.TryGetValue(viewModelProperty.Name, out var componentProperty))\n            {\n                throw new ParameterException(\n                    $\"Failed to find matching component parameter {viewModelProperty.Name} for view model {viewModelProperty.DeclaringType!.FullName}\"\n                );\n            }\n\n            _parameters.Add(componentProperty, viewModelProperty);\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Parameters/ParameterResolver.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Parameters;\n\ninternal interface IParameterResolver\n{\n    ParameterInfo ResolveParameters(Type componentType, Type viewModelType);\n}\n\ninternal class ParameterResolver : IParameterResolver\n{\n    private readonly IParameterCache _parameterCache;\n\n    public ParameterResolver(IParameterCache parameterCache)\n    {\n        _parameterCache = parameterCache;\n    }\n\n    public ParameterInfo ResolveParameters(Type componentType, Type viewModelType)\n    {\n        var parameterInfo = _parameterCache.Get(componentType);\n        if (parameterInfo is not null)\n        {\n            return parameterInfo;\n        }\n\n        var componentParameters = ResolveTypeParameters(componentType);\n        var viewModelParameters = ResolveTypeParameters(viewModelType);\n\n        parameterInfo = new ParameterInfo(componentParameters, viewModelParameters);\n        _parameterCache.Set(componentType, parameterInfo);\n\n        return parameterInfo;\n    }\n\n    private static IEnumerable<PropertyInfo> ResolveTypeParameters(Type memberType)\n    {\n        var componentProperties = memberType.GetProperties();\n\n        var resolvedComponentProperties = new List<PropertyInfo>();\n        foreach (var componentProperty in componentProperties)\n        {\n            // Skip if property has no public setter\n            if (componentProperty.GetSetMethod() is null)\n            {\n                continue;\n            }\n\n            // If the property is marked as a parameter add it to the list\n            ParameterAttribute? GetParameterAttribute() => componentProperty.GetCustomAttribute<ParameterAttribute>();\n            CascadingParameterAttribute? GetCascadingParameterAttribute() => componentProperty.GetCustomAttribute<CascadingParameterAttribute>();\n            if (GetParameterAttribute() != null || GetCascadingParameterAttribute() != null)\n            {\n                resolvedComponentProperties.Add(componentProperty);\n            }\n        }\n\n        return resolvedComponentProperties;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/Parameters/ViewModelParameterSetter.cs",
    "content": "﻿namespace MvvmBlazor.Internal.Parameters;\n\npublic interface IViewModelParameterSetter\n{\n    void ResolveAndSet(ComponentBase component, ViewModelBase viewModel);\n}\n\ninternal class ViewModelParameterSetter : IViewModelParameterSetter\n{\n    private readonly IParameterResolver _parameterResolver;\n\n    public ViewModelParameterSetter(IParameterResolver parameterResolver)\n    {\n        _parameterResolver = parameterResolver;\n    }\n\n    public void ResolveAndSet(ComponentBase component, ViewModelBase viewModel)\n    {\n        var componentType = component.GetType();\n        var viewModelType = viewModel.GetType();\n\n        var parameterInfo = _parameterResolver.ResolveParameters(componentType, viewModelType);\n        foreach (var (componentProperty, viewModelProperty) in parameterInfo.Parameters)\n        {\n            var value = componentProperty.GetValue(component);\n            var parameterTypeDiffers = componentProperty.PropertyType != viewModelProperty.PropertyType;\n            if (value != null && parameterTypeDiffers)\n            {\n                value = ConvertValue(componentProperty.PropertyType, viewModelProperty.PropertyType, value);\n            }\n\n            viewModelProperty.SetValue(viewModel, value);\n        }\n    }\n\n    private static object? ConvertValue(Type componentType, Type viewModelType, object value)\n    {\n        var converter = TypeDescriptor.GetConverter(viewModelType);\n        return converter.CanConvertFrom(componentType) ? converter.ConvertTo(value, viewModelType) : value;\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/WeakEventListener/WeakEventListener.cs",
    "content": "﻿namespace MvvmBlazor.Internal.WeakEventListener;\n\ninternal interface IWeakEventListener\n{\n    bool IsAlive { get; }\n    object? Source { get; }\n    Delegate? Handler { get; }\n    void StopListening();\n}\n\ninternal abstract class WeakEventListenerBase<T, TArgs> : IWeakEventListener where T : class where TArgs : EventArgs\n{\n    private readonly WeakReference<Action<T, TArgs>> _handler;\n    private readonly WeakReference<T> _source;\n\n    protected WeakEventListenerBase(T source, Action<T, TArgs> handler)\n    {\n        ArgumentNullException.ThrowIfNull(source);\n        ArgumentNullException.ThrowIfNull(handler);\n\n        _source = new WeakReference<T>(source);\n        _handler = new WeakReference<Action<T, TArgs>>(handler);\n    }\n\n    public bool IsAlive => _handler.TryGetTarget(out _) && _source.TryGetTarget(out _);\n\n    public object? Source\n    {\n        get\n        {\n            if (_source.TryGetTarget(out var source))\n            {\n                return source;\n            }\n\n            return null;\n        }\n    }\n\n    public Delegate? Handler\n    {\n        get\n        {\n            if (_handler.TryGetTarget(out var handler))\n            {\n                return handler;\n            }\n\n            return null;\n        }\n    }\n\n    public void StopListening()\n    {\n        if (_source.TryGetTarget(out var source))\n        {\n            StopListening(source);\n        }\n    }\n\n    protected void HandleEvent(object sender, TArgs e)\n    {\n        if (_handler.TryGetTarget(out var handler))\n        {\n            handler((T)sender, e);\n        }\n        else\n        {\n            StopListening();\n        }\n    }\n\n    protected abstract void StopListening(T source);\n}\n\ninternal class TypedWeakEventListener<T, TArgs> : WeakEventListenerBase<T, TArgs>\n    where T : class where TArgs : EventArgs\n{\n    private readonly Action<T, EventHandler<TArgs>> _unregister;\n\n    public TypedWeakEventListener(\n        T source,\n        Action<T, EventHandler<TArgs>> register,\n        Action<T, EventHandler<TArgs>> unregister,\n        Action<T, TArgs> handler) : base(source, handler)\n    {\n        ArgumentNullException.ThrowIfNull(register);\n        ArgumentNullException.ThrowIfNull(unregister);\n\n        _unregister = unregister;\n        register(source, HandleEvent!);\n    }\n\n    protected override void StopListening(T source)\n    {\n        _unregister(source, HandleEvent!);\n    }\n}\n\ninternal class PropertyChangedWeakEventListener<T> : WeakEventListenerBase<T, PropertyChangedEventArgs>\n    where T : class, INotifyPropertyChanged\n{\n    public PropertyChangedWeakEventListener(T source, Action<T, PropertyChangedEventArgs> handler) : base(\n        source,\n        handler\n    )\n    {\n        source.PropertyChanged += HandleEvent!;\n    }\n\n    protected override void StopListening(T source)\n    {\n        source.PropertyChanged -= HandleEvent!;\n    }\n}\n\ninternal class CollectionChangedWeakEventListener<T> : WeakEventListenerBase<T, NotifyCollectionChangedEventArgs>\n    where T : class, INotifyCollectionChanged\n{\n    public CollectionChangedWeakEventListener(T source, Action<T, NotifyCollectionChangedEventArgs> handler) : base(\n        source,\n        handler\n    )\n    {\n        source.CollectionChanged += HandleEvent!;\n    }\n\n    protected override void StopListening(T source)\n    {\n        source.CollectionChanged -= HandleEvent!;\n    }\n}\n\ninternal class WeakEventListener<T, TArgs> : WeakEventListenerBase<T, TArgs> where T : class where TArgs : EventArgs\n{\n    private readonly EventInfo _eventInfo;\n\n    public WeakEventListener(T source, string eventName, Action<T, TArgs> handler) : base(source, handler)\n    {\n        _eventInfo = source.GetType().GetEvent(eventName) ??\n                     throw new ArgumentException(\"Unknown Event Name\", nameof(eventName));\n        if (_eventInfo.EventHandlerType == typeof(EventHandler<TArgs>))\n        {\n            _eventInfo.AddEventHandler(source, new EventHandler<TArgs>(HandleEvent!));\n        }\n        else //the event type isn't just an EventHandler<> so we have to create the delegate using reflection\n        {\n            _eventInfo.AddEventHandler(\n                source,\n                Delegate.CreateDelegate(_eventInfo.EventHandlerType!, this, nameof(HandleEvent))\n            );\n        }\n    }\n\n    protected override void StopListening(T source)\n    {\n        if (_eventInfo.EventHandlerType == typeof(EventHandler<TArgs>))\n        {\n            _eventInfo.RemoveEventHandler(source, new EventHandler<TArgs>(HandleEvent!));\n        }\n        else\n        {\n            _eventInfo.RemoveEventHandler(\n                source,\n                Delegate.CreateDelegate(_eventInfo.EventHandlerType!, this, nameof(HandleEvent))\n            );\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/Internal/WeakEventListener/WeakEventManager.cs",
    "content": "﻿namespace MvvmBlazor.Internal.WeakEventListener;\n\ninternal interface IWeakEventManager\n{\n    /// <summary>\n    ///     Registers the given delegate as a handler for the event specified by `eventName` on the given source.\n    /// </summary>\n    void AddWeakEventListener<T, TArgs>(T source, string eventName, Action<T, TArgs> handler)\n        where T : class where TArgs : EventArgs;\n\n    /// <summary>\n    ///     Registers the given delegate as a handler for the INotifyPropertyChanged.PropertyChanged event\n    /// </summary>\n    void AddWeakEventListener<T>(T source, Action<T, PropertyChangedEventArgs> handler)\n        where T : class, INotifyPropertyChanged;\n\n    /// <summary>\n    ///     Registers the given delegate as a handler for the INotifyCollectionChanged.CollectionChanged event\n    /// </summary>\n    void AddWeakEventListener<T>(T source, Action<T, NotifyCollectionChangedEventArgs> handler)\n        where T : class, INotifyCollectionChanged;\n\n    /// <summary>\n    ///     Unregisters any previously registered weak event handlers on the given source object\n    /// </summary>\n    void RemoveWeakEventListener<T>(T source) where T : class;\n\n    /// <summary>\n    ///     Unregisters all weak event listeners that have been registered by this weak event manager instance\n    /// </summary>\n    void ClearWeakEventListeners();\n}\n\npublic class WeakEventManager : IWeakEventManager\n{\n    private readonly Dictionary<IWeakEventListener, Delegate> _listeners = new();\n\n    /// <summary>\n    ///     Registers the given delegate as a handler for the event specified by `eventName` on the given source.\n    /// </summary>\n    public void AddWeakEventListener<T, TArgs>(T source, string eventName, Action<T, TArgs> handler)\n        where T : class where TArgs : EventArgs\n    {\n        ArgumentNullException.ThrowIfNull(source);\n\n        _listeners.Add(new WeakEventListener<T, TArgs>(source, eventName, handler), handler);\n    }\n\n    /// <summary>\n    ///     Registers the given delegate as a handler for the INotifyPropertyChanged.PropertyChanged event\n    /// </summary>\n    public void AddWeakEventListener<T>(T source, Action<T, PropertyChangedEventArgs> handler)\n        where T : class, INotifyPropertyChanged\n    {\n        ArgumentNullException.ThrowIfNull(source);\n\n        _listeners.Add(new PropertyChangedWeakEventListener<T>(source, handler), handler);\n    }\n\n    /// <summary>\n    ///     Registers the given delegate as a handler for the INotifyCollectionChanged.CollectionChanged event\n    /// </summary>\n    public void AddWeakEventListener<T>(T source, Action<T, NotifyCollectionChangedEventArgs> handler)\n        where T : class, INotifyCollectionChanged\n    {\n        ArgumentNullException.ThrowIfNull(source);\n\n        _listeners.Add(new CollectionChangedWeakEventListener<T>(source, handler), handler);\n    }\n\n    /// <summary>\n    ///     Unregisters any previously registered weak event handlers on the given source object\n    /// </summary>\n    public void RemoveWeakEventListener<T>(T source) where T : class\n    {\n        ArgumentNullException.ThrowIfNull(source);\n\n        var toRemove = new List<IWeakEventListener>();\n        foreach (var listener in _listeners.Keys)\n            if (!listener.IsAlive)\n            {\n                toRemove.Add(listener);\n            }\n            else if (listener.Source == source)\n            {\n                listener.StopListening();\n                toRemove.Add(listener);\n            }\n\n        foreach (var item in toRemove) _listeners.Remove(item);\n    }\n\n    /// <summary>\n    ///     Unregisters all weak event listeners that have been registered by this weak event manager instance\n    /// </summary>\n    public void ClearWeakEventListeners()\n    {\n        foreach (var listener in _listeners.Keys)\n            if (listener.IsAlive)\n            {\n                listener.StopListening();\n            }\n\n        _listeners.Clear();\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Core/MvvmBlazor.Core.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net6.0</TargetFramework>\n    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>\n    <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\\GeneratedFiles</CompilerGeneratedFilesOutputPath>\n    <RootNamespace>MvvmBlazor</RootNamespace>\n  </PropertyGroup>\n\n  <PropertyGroup Condition=\"'$(CI)' == 'true'\">\n    <Deterministic>true</Deterministic>\n    <PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>\n    <PackageLicenseExpression>MIT</PackageLicenseExpression>\n    <Authors>Christian Klemm</Authors>\n    <Description>A lightweight Blazor Mvvm Library</Description>\n    <PackageProjectUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</PackageProjectUrl>\n    <RepositoryUrl>$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)</RepositoryUrl>\n    <RepositoryType>git</RepositoryType>\n    <PackageTags>Blazor;Mvvm</PackageTags>\n    <PublishRepositoryUrl>true</PublishRepositoryUrl>\n    <IncludeSymbols>true</IncludeSymbols>\n    <EmbedUntrackedSources>true</EmbedUntrackedSources>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"Microsoft.AspNetCore.Components\" Version=\"6.0.0\" />\n    <PackageReference Include=\"Microsoft.CodeAnalysis.NetAnalyzers\" Version=\"6.0.0\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.SourceLink.GitHub\" Version=\"1.1.1\" PrivateAssets=\"All\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\" OutputItemType=\"Analyzer\" ReferenceOutputAssembly=\"false\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "src/MvvmBlazor.Core/NotifyAttribute.cs",
    "content": "﻿// ReSharper disable once CheckNamespace\n\nnamespace MvvmBlazor;\n\n[AttributeUsage(AttributeTargets.Field)]\npublic sealed class NotifyAttribute : Attribute { }"
  },
  {
    "path": "src/MvvmBlazor.Core/Properties/AssemblyInfo.cs",
    "content": "﻿[assembly: InternalsVisibleTo(\"MvvmBlazor.Tests\")]\n[assembly: InternalsVisibleTo(\"DynamicProxyGenAssembly2\")]\n[assembly: CLSCompliant(false)]"
  },
  {
    "path": "src/MvvmBlazor.Core/Properties/GlobalSuppressions.cs",
    "content": "﻿// This file is used by Code Analysis to maintain SuppressMessage\n// attributes that are applied to this project.\n// Project-level suppressions either have no target or are given\n// a specific target and scoped to a namespace, type, member, etc.\n\nusing System.Diagnostics.CodeAnalysis;\n\n[assembly: SuppressMessage(\"Globalization\", \"CA1303:Do not pass literals as localized parameters\")]"
  },
  {
    "path": "src/MvvmBlazor.Core/ViewModel/ViewModelBase.cs",
    "content": "namespace MvvmBlazor.ViewModel;\n\npublic abstract class ViewModelBase : INotifyPropertyChanged\n{\n    private readonly Dictionary<string, List<Func<object, Task>>> _subscriptions = new();\n\n    public IServiceProvider RootServiceProvider { get; set; } = null!;\n\n    public event PropertyChangedEventHandler? PropertyChanged;\n\n    protected bool Set<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)\n    {\n        return Set(ref field, value, EqualityComparer<T>.Default, propertyName);\n    }\n\n    protected bool Set<T>(ref T field, T value, IEqualityComparer<T> equalityComparer, [CallerMemberName] string? propertyName = null)\n    {\n        ArgumentNullException.ThrowIfNull(equalityComparer);\n        if (!equalityComparer.Equals(field, value))\n        {\n            field = value;\n            OnPropertyChanged(propertyName!);\n            if (!_subscriptions.ContainsKey(propertyName!))\n            {\n                return true;\n            }\n\n            foreach (var action in _subscriptions[propertyName!]) action(value!);\n            return true;\n        }\n\n        return false;\n    }\n\n    public virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)\n    {\n        ArgumentNullException.ThrowIfNull(propertyName);\n        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n    }\n\n    protected void Subscribe<T>(Expression<Func<T>>? expression, Action<T> action)\n    {\n        SubscribeAsync(\n            expression,\n            arg =>\n            {\n                action(arg);\n                return Task.CompletedTask;\n            }\n        );\n    }\n\n    protected void SubscribeAsync<T>(Expression<Func<T>>? property, Func<T, Task> func)\n    {\n        if (property is null)\n        {\n            throw new BindingException(\"Property cannot be null\");\n        }\n\n        if (!(property.Body is MemberExpression m))\n        {\n            throw new BindingException(\"Subscription member must be a property\");\n        }\n\n        if (!(m.Member is PropertyInfo propertyInfo))\n        {\n            throw new BindingException(\"Subscription member must be a property\");\n        }\n\n        var propertyName = propertyInfo.Name;\n        if (!_subscriptions.ContainsKey(propertyName))\n        {\n            _subscriptions[propertyName] = new List<Func<object, Task>>();\n        }\n\n        _subscriptions[propertyName].Add(async value => await func((T)value).ConfigureAwait(false));\n    }\n\n    #region Lifecycle Methods\n\n    /// <summary>\n    ///     Method invoked when the component is ready to start, having received its\n    ///     initial parameters from its parent in the render tree.\n    /// </summary>\n    public virtual void OnInitialized() { }\n\n    /// <summary>\n    ///     Method invoked when the component is ready to start, having received its\n    ///     initial parameters from its parent in the render tree.\n    ///     Override this method if you will perform an asynchronous operation and\n    ///     want the component to refresh when that operation is completed.\n    /// </summary>\n    /// <returns>A <see cref=\"Task\" /> representing any asynchronous operation.</returns>\n    public virtual Task OnInitializedAsync()\n    {\n        return Task.CompletedTask;\n    }\n\n    /// <summary>\n    ///     Method invoked when the component has received parameters from its parent in\n    ///     the render tree, and the incoming values have been assigned to properties.\n    /// </summary>\n    public virtual void OnParametersSet() { }\n\n    /// <summary>\n    ///     Method invoked when the component has received parameters from its parent in\n    ///     the render tree, and the incoming values have been assigned to properties.\n    /// </summary>\n    /// <returns>A <see cref=\"Task\" /> representing any asynchronous operation.</returns>\n    public virtual Task OnParametersSetAsync()\n    {\n        return Task.CompletedTask;\n    }\n\n    /// <summary>\n    ///     Notifies the component that its state has changed. When applicable, this will\n    ///     cause the component to be re-rendered.\n    /// </summary>\n    protected void StateHasChanged()\n    {\n        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));\n    }\n\n    /// <summary>\n    ///     Returns a flag to indicate whether the component should render.\n    /// </summary>\n    /// <returns></returns>\n    public virtual bool ShouldRender()\n    {\n        return true;\n    }\n\n    /// <summary>\n    ///     Method invoked after each time the component has been rendered.\n    /// </summary>\n    /// <param name=\"firstRender\">\n    ///     Set to <c>true</c> if this is the first time\n    ///     <see cref=\"ComponentBase.OnAfterRender(bool)\" /> has been invoked\n    ///     on this component instance; otherwise <c>false</c>.\n    /// </param>\n    /// <remarks>\n    ///     The <see cref=\"ComponentBase.OnAfterRender(bool)\" /> and\n    ///     <see cref=\"ComponentBase.OnAfterRenderAsync(bool)\" /> lifecycle methods\n    ///     are useful for performing interop, or interacting with values received from <c>@ref</c>.\n    ///     Use the <paramref name=\"firstRender\" /> parameter to ensure that initialization work is only performed\n    ///     once.\n    /// </remarks>\n    public virtual void OnAfterRender(bool firstRender) { }\n\n    /// <summary>\n    ///     Method invoked after each time the component has been rendered. Note that the component does\n    ///     not automatically re-render after the completion of any returned <see cref=\"Task\" />,\n    ///     because\n    ///     that would cause an infinite render loop.\n    /// </summary>\n    /// <param name=\"firstRender\">\n    ///     Set to <c>true</c> if this is the first time\n    ///     <see cref=\"ComponentBase.OnAfterRender(bool)\" /> has been invoked\n    ///     on this component instance; otherwise <c>false</c>.\n    /// </param>\n    /// <returns>A <see cref=\"Task\" /> representing any asynchronous operation.</returns>\n    /// <remarks>\n    ///     The <see cref=\"ComponentBase.OnAfterRender(bool)\" /> and\n    ///     <see cref=\"ComponentBase.OnAfterRenderAsync(bool)\" /> lifecycle methods\n    ///     are useful for performing interop, or interacting with values received from <c>@ref</c>.\n    ///     Use the <paramref name=\"firstRender\" /> parameter to ensure that initialization work is only performed\n    ///     once.\n    /// </remarks>\n    public virtual Task OnAfterRenderAsync(bool firstRender)\n    {\n        return Task.CompletedTask;\n    }\n\n    /// <summary>\n    ///     Sets parameters supplied by the component's parent in the render tree.\n    /// </summary>\n    /// <param name=\"parameters\">The parameters.</param>\n    /// <returns>\n    ///     A <see cref=\"Task\" /> that completes when the component has finished updating and\n    ///     rendering itself.\n    /// </returns>\n    /// <remarks>\n    ///     <para>\n    ///         The\n    ///         <see\n    ///             cref=\"ComponentBase.SetParametersAsync(ParameterView)\" />\n    ///         method should be passed the entire set of parameter values each\n    ///         time\n    ///         <see\n    ///             cref=\"ComponentBase.SetParametersAsync(ParameterView)\" />\n    ///         is called. It not required that the caller supply a parameter\n    ///         value for all parameters that are logically understood by the component.\n    ///     </para>\n    ///     <para>\n    ///         The default implementation of\n    ///         <see\n    ///             cref=\"ComponentBase.SetParametersAsync(ParameterView)\" />\n    ///         will set the value of each property\n    ///         decorated with <see cref=\"ParameterAttribute\" /> or\n    ///         <see cref=\"CascadingParameterAttribute\" /> that has\n    ///         a corresponding value in the <see cref=\"ParameterView\" />. Parameters that do\n    ///         not have a corresponding value\n    ///         will be unchanged.\n    ///     </para>\n    /// </remarks>\n    public virtual Task SetParametersAsync(ParameterView parameters)\n    {\n        return Task.CompletedTask;\n    }\n\n    #endregion\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/.editorconfig",
    "content": "﻿[*.cs]\ndotnet_diagnostic.CA1707.severity = none\ndotnet_diagnostic.CA1812.severity = none"
  },
  {
    "path": "src/MvvmBlazor.Tests/Abstractions/StrictMock.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Abstractions;\n\ninternal class StrictMock<T> : Mock<T> where T : class\n{\n    public StrictMock() : base(MockBehavior.Strict) { }\n    public StrictMock(params object[] args) : base(MockBehavior.Strict, args) { }\n    public StrictMock(Expression<Func<T>> newExpression) : base(newExpression, MockBehavior.Strict) { }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Abstractions/UnitTest.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Abstractions;\n\npublic abstract class UnitTest : IDisposable\n{\n    private readonly ServiceProvider _services;\n    protected IServiceProvider Services => _services;\n\n    protected UnitTest(ITestOutputHelper outputHelper)\n    {\n        _services = BuildProvider(outputHelper);\n    }\n\n    private ServiceProvider BuildProvider(ITestOutputHelper testOutputHelper)\n    {\n        var serviceCollection = new ServiceCollection();\n        serviceCollection.AddSingleton(testOutputHelper);\n\n        RegisterServices(serviceCollection);\n\n        return serviceCollection.BuildServiceProvider();\n    }\n\n    protected virtual void RegisterServices(IServiceCollection services) { }\n\n    public void Dispose()\n    {\n        Dispose(true);\n        GC.SuppressFinalize(this);\n    }\n\n    protected virtual void Dispose(bool disposing)\n    {\n        if (disposing)\n        {\n            _services.Dispose();\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Components/MvvmComponentBaseTTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Components;\n\npublic class MvvmComponentBaseTTests : UnitTest\n{\n    public MvvmComponentBaseTTests(ITestOutputHelper outputHelper) : base(outputHelper) { }\n\n    protected override void RegisterServices(IServiceCollection services)\n    {\n        var binder = services.StrictMock<IBinder>();\n        services.StrictMock<ViewModelBase>();\n        services.StrictMock<IViewModelParameterSetter>();\n        services.AddSingleton<MockMvvmComponentBase>();\n        services.AddSingleton<TestViewModel>();\n\n        binder.SetupSet(x => x.ValueChangedCallback = It.IsAny<Action<IBinding, EventArgs>>()).Verifiable();\n    }\n\n    [Fact]\n    public void AfterRender_called_On_binding_context()\n    {\n        var viewModel = Services.GetMock<ViewModelBase>();\n        viewModel.Setup(x => x.OnAfterRender(true)).Verifiable();\n\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n        component.AfterRender(true);\n\n        viewModel.Verify();\n    }\n\n    [Fact]\n    public async Task AfterRenderAsync_called_on_binding_context()\n    {\n        var task = Task.CompletedTask;\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.OnAfterRenderAsync(It.IsAny<bool>())).Returns(task).Verifiable();\n\n        await component.AfterRenderAsync(true);\n\n        viewModel.Verify();\n    }\n\n    [Fact]\n    public void Bind_binds_binding_context()\n    {\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binder = Services.GetMock<IBinder>();\n\n        binder.Setup(x => x.Bind(viewModel, x => x.TestProperty));\n\n        var component = new Mock<MvvmComponentBase<TestViewModel>>(Services.GetRequiredService<IServiceScopeFactory>());\n\n        component.Setup(x => x.AddBinding(viewModel, x => x.TestProperty)).Verifiable();\n        component.Object.Bind(x => x.TestProperty);\n\n        component.Verify();\n        component.VerifyNoOtherCalls();\n    }\n\n    [Fact]\n    public void OnInitialized_called_on_binding_context()\n    {\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var viewModelParameterSetter = Services.GetMock<IViewModelParameterSetter>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.OnInitialized()).Verifiable();\n        viewModelParameterSetter.Setup(x => x.ResolveAndSet(component, viewModel.Object)).Verifiable();\n\n        component.Initialized();\n\n        viewModel.Verify();\n    }\n\n    [Fact]\n    public async Task OnInitializedAsync_called_on_binding_context()\n    {\n        var task = Task.CompletedTask;\n\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.OnInitializedAsync()).Returns(task).Verifiable();\n\n        await component.InitializedAsync();\n\n        viewModel.Verify();\n    }\n\n    [Fact]\n    public void OnParametersSet_sets_viewmodel_parameters()\n    {\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var viewModelParameterSetter = Services.GetMock<IViewModelParameterSetter>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.OnParametersSet()).Verifiable();\n        viewModelParameterSetter.Setup(x => x.ResolveAndSet(component, viewModel.Object)).Verifiable();\n\n        component.ParametersSet();\n\n        viewModelParameterSetter.Verify();\n    }\n\n    [Fact]\n    public async Task OnParametersSetAsync_called_on_binding_context()\n    {\n        var task = Task.CompletedTask;\n\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.OnParametersSetAsync()).Returns(task).Verifiable();\n\n        await component.ParametersSetAsync();\n\n        viewModel.Verify();\n    }\n\n    [Fact]\n    public void Sets_binding_context()\n    {\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        component.Context.ShouldBe(viewModel.Object);\n    }\n\n    [Fact]\n    public void ShouldRender_called_on_binding_context()\n    {\n        var viewModel = Services.GetMock<ViewModelBase>();\n        var component = Services.GetRequiredService<MockMvvmComponentBase>();\n\n        viewModel.Setup(x => x.ShouldRender()).Returns(true).Verifiable();\n\n        var res = component.Render();\n        res.ShouldBe(true);\n\n        viewModel.Verify();\n    }\n\n    private class MockMvvmComponentBase : MvvmComponentBase<ViewModelBase>\n    {\n        public ViewModelBase Context => BindingContext;\n        public MockMvvmComponentBase(IServiceProvider services) : base(services) { }\n\n        public void Initialized()\n        {\n            OnInitialized();\n        }\n\n        public Task InitializedAsync()\n        {\n            return OnInitializedAsync();\n        }\n\n        public void ParametersSet()\n        {\n            OnParametersSet();\n        }\n\n        public Task ParametersSetAsync()\n        {\n            return OnParametersSetAsync();\n        }\n\n        public bool Render()\n        {\n            return ShouldRender();\n        }\n\n        public void AfterRender(bool firstRender)\n        {\n            OnAfterRender(firstRender);\n        }\n\n        public Task AfterRenderAsync(bool firstRender)\n        {\n            return OnAfterRenderAsync(firstRender);\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Components/MvvmComponentBaseTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Components;\n\npublic class MvvmComponentBaseTests : UnitTest\n{\n    public MvvmComponentBaseTests(ITestOutputHelper outputHelper) : base(outputHelper) { }\n\n    protected override void RegisterServices(IServiceCollection services)\n    {\n        var binder = services.StrictMock<IBinder>();\n        services.AddSingleton<TestComponent>();\n\n        binder.SetupSet(x => x.ValueChangedCallback = It.IsAny<Action<IBinding, EventArgs>>()).Verifiable();\n    }\n\n    [Fact]\n    public void AddBinding_adds_Binding()\n    {\n        var viewModel = new TestViewModel();\n        var binder = Services.GetMock<IBinder>();\n        binder.Setup(x => x.Bind(viewModel, y => y.TestProperty)).Returns(\"Test\").Verifiable();\n\n        var component = Services.GetRequiredService<TestComponent>();\n        var res = component.AddBinding(viewModel, x => x.TestProperty);\n        res.ShouldBe(\"Test\");\n\n        binder.Verify();\n    }\n\n    [Fact]\n    public void Bind_adds_Binding()\n    {\n        var viewModel = new TestViewModel();\n\n        var component = new Mock<MvvmComponentBase>(Services.GetRequiredService<IServiceScopeFactory>());\n        component.Setup(x => x.AddBinding(viewModel, y => y.TestProperty)).Returns(\"Test\").Verifiable();\n\n        var res = component.Object.Bind(viewModel, x => x.TestProperty);\n        res.ShouldBe(\"Test\");\n\n        component.Verify();\n    }\n\n    internal class TestComponent : MvvmComponentBase\n    {\n        public Action? BindingChangedAction { get; set; }\n\n\n        public TestComponent(IServiceProvider services) : base(services) { }\n\n        internal override void BindingOnBindingValueChanged(object sender, EventArgs e)\n        {\n            BindingChangedAction?.Invoke();\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Components/TestViewModel.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Components;\n\npublic class TestViewModel : ViewModelBase\n{\n    private string? _testProperty;\n\n    public string? TestProperty\n    {\n        get => _testProperty;\n        set => Set(ref _testProperty, value);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Extensions/ServiceCollectionExtensions.cs",
    "content": "﻿// ReSharper disable once CheckNamespace\n\nnamespace Microsoft.Extensions.DependencyInjection;\n\ninternal static class ServiceCollectionExtensions\n{\n    public static Mock<T> Mock<T>(this IServiceCollection services, params object[] args) where T : class\n    {\n        var mock = new Mock<T>(args);\n        services.AddSingleton(mock);\n        services.AddSingleton(mock.Object);\n        return mock;\n    }\n\n    public static Mock<T> StrictMock<T>(this IServiceCollection services) where T : class\n    {\n        var mock = new StrictMock<T>();\n        services.AddSingleton<Mock<T>>(mock);\n        services.AddSingleton(mock.Object);\n        return mock;\n    }\n\n    public static IServiceCollection Provide<T>(this IServiceCollection services) where T : class\n    {\n        return services.AddSingleton<T>();\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Extensions/ServiceProviderExtensions.cs",
    "content": "﻿// ReSharper disable once CheckNamespace\n\nnamespace Microsoft.Extensions.DependencyInjection;\n\ninternal static class ServiceProviderExtensions\n{\n    public static Mock<T> GetMock<T>(this IServiceProvider provider) where T : class\n    {\n        return provider.GetRequiredService<Mock<T>>();\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Generators/MvvmComponentGeneratorTests.cs",
    "content": "﻿using Binder = System.Reflection.Binder;\n\nnamespace MvvmBlazor.Tests.Generators;\n\npublic class MvvmComponentGeneratorTests\n{\n    [Fact]\n    public void Generates_error_when_component_is_not_partial()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public class TestComponent : Microsoft.AspNetCore.Components.ComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR001\");\n    }\n\n    [Fact]\n    public void Generates_error_when_component_is_not_inheriting()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR002\");\n    }\n\n    [Fact]\n    public void Generates_error_when_generic_type_parameter_count_is_wrong()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent<T, T1> : Microsoft.AspNetCore.Components.ComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR005\");\n    }\n\n    [Fact]\n    public void Generates_error_when_generic_type_parameter_name_is_wrong()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent<T1> : Microsoft.AspNetCore.Components.ComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR005\");\n    }\n\n    [Fact]\n    public void Generates_component_with_component_base_class()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent : Microsoft.AspNetCore.Components.ComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    [Fact]\n    public void Generates_component_with_owning_component_base_class()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent : Microsoft.AspNetCore.Components.OwningComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    [Fact]\n    public void Generates_generic_component()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                [{nameof(MvvmComponentAttribute)}]\n                public partial class TestComponent<T> : Microsoft.AspNetCore.Components.OwningComponentBase {{}}\n            \"\n        );\n\n        var generator = new MvvmComponentGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    private static Compilation CreateCompilation(string source)\n    {\n        return CSharpCompilation.Create(\n            \"compilation\",\n            new[] { CSharpSyntaxTree.ParseText(source) },\n            new[]\n            {\n                MetadataReference.CreateFromFile(typeof(Binder).GetTypeInfo().Assembly.Location),\n                MetadataReference.CreateFromFile(typeof(ComponentBase).GetTypeInfo().Assembly.Location)\n            },\n            new CSharpCompilationOptions(OutputKind.ConsoleApplication)\n        );\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Generators/NotifyPropertyChangedGeneratorTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Generators;\n\npublic class NotifyPropertyChangedGeneratorTests\n{\n    [Fact]\n    public void Generates_error_when_viewmodel_is_not_partial()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public class TestViewModel : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR003\");\n    }\n\n    [Fact]\n    public void Generates_error_when_view_model_is_not_inheriting()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public partial class TestViewModel\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldNotBeEmpty();\n        diagnostics.First().Id.ShouldBe(\"MVVMBLAZOR004\");\n    }\n\n    [Fact]\n    public void Generates_viewmodel()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public partial class TestViewModel : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n\n                    public TestViewModel()\n                    {{\n                        Test = true;\n                    }}\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    [Fact]\n    public void Generates_viewmodel_for_abstract_class()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public abstract partial class TestViewModel : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n\n                public TestViewModel()\n                {{\n                    Test = true;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    [Fact]\n    public void Generates_viewmodel_for_abstract_class_with_inheritance()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public abstract partial class BaseViewModel : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _foo;\n                }}\n\n                public abstract partial class TestViewModel : BaseViewModel\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n\n                public TestViewModel()\n                {{\n                    Test = true;\n                    Foo = true;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n\n    [Fact]\n    public void Generates_viewmodel_for_generic_class()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public abstract partial class TestViewModel<T> : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n\n                public TestViewModel()\n                {{\n                    Test = true;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    [Fact]\n    public void Generates_viewmodel_for_abstract_generic_class()\n    {\n        var inputCompilation = CreateCompilation(\n            @$\"\n                public abstract partial class TestViewModel<T> : MvvmBlazor.ViewModel.ViewModelBase\n                {{\n                    [{typeof(NotifyAttribute)}]\n                    private bool _test;\n                }}\n\n                public TestViewModel()\n                {{\n                    Test = true;\n                }}\n            \"\n        );\n\n        var generator = new NotifyPropertyChangedGenerator();\n        GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);\n\n        driver.RunGeneratorsAndUpdateCompilation(inputCompilation, out _, out var diagnostics);\n        diagnostics.ShouldBeEmpty();\n    }\n\n    private static Compilation CreateCompilation(string source)\n    {\n        return CSharpCompilation.Create(\n            \"compilation\",\n            new[] { CSharpSyntaxTree.ParseText(source) },\n            new[]\n            {\n                MetadataReference.CreateFromFile(typeof(MvvmComponentBase).GetTypeInfo().Assembly.Location)\n            },\n            new CSharpCompilationOptions(OutputKind.ConsoleApplication)\n        );\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/GlobalUsings.cs",
    "content": "﻿global using System;\nglobal using Microsoft.Extensions.DependencyInjection;\nglobal using Moq;\nglobal using MvvmBlazor.Components;\nglobal using MvvmBlazor.Internal.Bindings;\nglobal using MvvmBlazor.Tests.Abstractions;\nglobal using Shouldly;\nglobal using Xunit;\nglobal using Xunit.Abstractions;\nglobal using System.Linq;\nglobal using System.Reflection;\nglobal using Microsoft.AspNetCore.Components;\nglobal using Microsoft.CodeAnalysis;\nglobal using Microsoft.CodeAnalysis.CSharp;\nglobal using System.Threading.Tasks;\nglobal using MvvmBlazor.Internal.Parameters;\nglobal using MvvmBlazor.ViewModel;\nglobal using System.Linq.Expressions;\nglobal using System.Collections.Specialized;\nglobal using System.ComponentModel;\nglobal using MvvmBlazor.Internal.WeakEventListener;\nglobal using MvvmBlazor.CodeGenerators.Components;\nglobal using MvvmBlazor.CodeGenerators.NotifyPropertyChanged;"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Bindings/BinderTests.cs",
    "content": "﻿using Binder = MvvmBlazor.Internal.Bindings.Binder;\n\nnamespace MvvmBlazor.Tests.Internal.Bindings;\n\npublic class BinderTests : UnitTest\n{\n    public BinderTests(ITestOutputHelper outputHelper) : base(outputHelper) { }\n\n    protected override void RegisterServices(IServiceCollection services)\n    {\n        services.StrictMock<IBindingFactory>();\n        services.StrictMock<IWeakEventManager>();\n        services.Provide<TestViewModel>();\n        services.Provide<Binder>();\n    }\n\n    [Fact]\n    public void Bind_throws_when_callback_is_null()\n    {\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binder = Services.GetRequiredService<Binder>();\n\n        Should.Throw<BindingException>(() => binder.Bind(viewModel, x => x.Test));\n    }\n\n    [Fact]\n    public void Bind_throws_when_view_model_is_null()\n    {\n        var binder = Services.GetRequiredService<Binder>();\n\n        var callback = (IBinding b, EventArgs a) => { };\n        binder.ValueChangedCallback = callback;\n\n        Should.Throw<BindingException>(() => binder.Bind<TestViewModel, string>(null!, x => x.Test!));\n    }\n\n    [Fact]\n    public void Bind_throws_when_property_expression_is_null()\n    {\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binder = Services.GetRequiredService<Binder>();\n\n        var callback = (IBinding b, EventArgs a) => { };\n        binder.ValueChangedCallback = callback;\n\n        Should.Throw<BindingException>(() => binder.Bind<TestViewModel, string>(viewModel, null!));\n    }\n\n    [Fact]\n    public void Bind_throws_when_property_expression_is_not_property()\n    {\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binder = Services.GetRequiredService<Binder>();\n\n        var callback = (IBinding b, EventArgs a) => { };\n        binder.ValueChangedCallback = callback;\n\n        Should.Throw<BindingException>(() => binder.Bind(viewModel, x => x.PublicField));\n    }\n\n    [Fact]\n    public void Bind_binds_property()\n    {\n        var bindingFactory = Services.GetMock<IBindingFactory>();\n        var weakEventManager = Services.GetMock<IWeakEventManager>();\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binding = new Mock<IBinding>();\n\n        bindingFactory.Setup(x => x.Create(viewModel, It.IsAny<PropertyInfo>(), weakEventManager.Object))\n            .Returns(binding.Object)\n            .Verifiable();\n\n        binding.Setup(x => x.GetValue()).Returns(\"test\").Verifiable();\n        weakEventManager.Setup(\n                x => x.AddWeakEventListener(\n                    binding.Object,\n                    nameof(Binding.BindingValueChanged),\n                    It.IsAny<Action<IBinding, EventArgs>>()\n                )\n            )\n            .Verifiable();\n        weakEventManager.Setup(x => x.RemoveWeakEventListener(binding.Object));\n\n        var callback = (IBinding b, EventArgs a) => { };\n\n        var binder = Services.GetRequiredService<Binder>();\n        binder.ValueChangedCallback = callback;\n\n        var res = binder.Bind(viewModel, x => x.Test);\n        res.ShouldBe(\"test\");\n\n        bindingFactory.Verify();\n        binding.Verify();\n        weakEventManager.Verify();\n    }\n\n    [Fact]\n    public void Bind_binds_property_exactly_once()\n    {\n        var bindingFactory = Services.GetMock<IBindingFactory>();\n        var weakEventManager = Services.GetMock<IWeakEventManager>();\n        var viewModel = Services.GetRequiredService<TestViewModel>();\n        var binding = new Mock<IBinding>();\n\n        bindingFactory.Setup(x => x.Create(viewModel, It.IsAny<PropertyInfo>(), weakEventManager.Object))\n            .Returns(binding.Object)\n            .Verifiable();\n\n        binding.Setup(x => x.GetValue()).Returns(\"test\").Verifiable();\n        weakEventManager.Setup(\n                x => x.AddWeakEventListener(\n                    binding.Object,\n                    nameof(Binding.BindingValueChanged),\n                    It.IsAny<Action<IBinding, EventArgs>>()\n                )\n            )\n            .Verifiable();\n        weakEventManager.Setup(x => x.RemoveWeakEventListener(binding.Object));\n\n        var callback = (IBinding b, EventArgs a) => { };\n\n        var binder = Services.GetRequiredService<Binder>();\n        binder.ValueChangedCallback = callback;\n\n        var res = binder.Bind(viewModel, x => x.Test);\n        res.ShouldBe(\"test\");\n\n        res = binder.Bind(viewModel, x => x.Test);\n        res.ShouldBe(\"test\");\n\n        weakEventManager.Verify(\n            x => x.AddWeakEventListener(\n                binding.Object,\n                nameof(Binding.BindingValueChanged),\n                It.IsAny<Action<IBinding, EventArgs>>()\n            ),\n            Times.Once\n        );\n        binding.Verify();\n        bindingFactory.Verify();\n        weakEventManager.Verify();\n    }\n\n    private class TestViewModel : ViewModelBase\n    {\n#pragma warning disable CA1051\n#pragma warning disable CS0649\n        public string? PublicField;\n#pragma warning restore CS0649\n#pragma warning restore CA1051\n        public string? Test { get; set; }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Bindings/BindingFactoryTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Internal.Bindings;\n\npublic class BindingFactoryTests\n{\n    [Fact]\n    public void Create_returns_binding()\n    {\n        var source = new Mock<INotifyPropertyChanged>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        var wem = new Mock<IWeakEventManager>();\n\n        var factory = new BindingFactory();\n        using var res = factory.Create(source.Object, propertyInfo.Object, wem.Object);\n        res.ShouldNotBeNull();\n        res.PropertyInfo.ShouldBe(propertyInfo.Object);\n        res.Source.ShouldBe(source.Object);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Bindings/BindingTests.cs",
    "content": "﻿using System.Collections.ObjectModel;\n\nnamespace MvvmBlazor.Tests.Internal.Bindings;\n\npublic class BindingTests\n{\n    [Fact]\n    public void Adds_collection_event_listener_when_initializing()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        propertyInfo.SetupSequence(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null))\n            .Returns(collection.Object);\n\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n\n        wem.Verify(\n            x => x.AddWeakEventListener(\n                It.IsAny<INotifyCollectionChanged>(),\n                It.IsAny<Action<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>>()\n            )\n        );\n    }\n\n    [Fact]\n    public void Adds_collection_event_listener_when_property_changes_to_not_null()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n        propertyInfo.Setup(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null)).Returns(collection.Object);\n\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(propertyName));\n        wem.Verify(\n            x => x.AddWeakEventListener(\n                It.IsAny<INotifyCollectionChanged>(),\n                It.IsAny<Action<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>>()\n            )\n        );\n    }\n\n    [Fact]\n    public void Dispose_removes_collection_listener()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n        propertyInfo.SetupSequence(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null))\n            .Returns(collection.Object)\n            .Returns((object?)null);\n\n        using (var binding = new Binding(source.Object, propertyInfo.Object, wem.Object))\n        {\n            binding.Initialize();\n        }\n\n        wem.Verify(x => x.RemoveWeakEventListener(collection.Object));\n    }\n\n    [Fact]\n    public void Dispose_removes_event_listener()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n        propertyInfo.Setup(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null)).Returns(collection.Object);\n\n        using (var binding = new Binding(source.Object, propertyInfo.Object, wem.Object))\n        {\n            binding.Initialize();\n        }\n\n        wem.Verify(x => x.RemoveWeakEventListener(source.Object));\n    }\n\n    [Fact]\n    public void Equals_not_different_source_and_property()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source1 = new Mock<INotifyPropertyChanged>();\n        var source2 = new Mock<INotifyPropertyChanged>();\n\n        var propertyInfo1 = new Mock<PropertyInfo>();\n        propertyInfo1.Setup(x => x.Name).Returns(propertyName);\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo2 = new Mock<PropertyInfo>();\n        propertyInfo2.Setup(x => x.Name).Returns(propertyName + \"Foo\");\n\n        using var binding1 = new Binding(source1.Object, propertyInfo1.Object, wem.Object);\n        using var binding2 = new Binding(source2.Object, propertyInfo2.Object, wem.Object);\n\n        binding1.GetHashCode().ShouldNotBe(binding2.GetHashCode());\n        binding1.Equals(binding2).ShouldBeFalse();\n    }\n\n    [Fact]\n    public void Equals_same_source_and_property()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var wem = new Mock<IWeakEventManager>();\n\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n\n        using var binding1 = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        using var binding2 = new Binding(source.Object, propertyInfo.Object, wem.Object);\n\n        binding1.GetHashCode().ShouldBe(binding2.GetHashCode());\n        binding1.Equals(binding2).ShouldBeTrue();\n    }\n\n    [Fact]\n    public void Ignores_PropertyChangedEvent_when_property_name_does_not_match()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n        propertyInfo.Setup(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null)).Returns(collection.Object);\n\n        var bindingValueChangedRaised = false;\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n        binding.BindingValueChanged += (s, e) => bindingValueChangedRaised = true;\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(\"foo\"));\n\n        bindingValueChangedRaised.ShouldBeFalse();\n    }\n\n    [Fact]\n    public void Does_not_raise_BindingValueChanged_when_uninitialized()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n\n        var hasChanged = false;\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.BindingValueChanged += (sender, args) => { hasChanged = true; };\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(propertyName));\n        hasChanged.ShouldBeFalse();\n    }\n\n    [Fact]\n    public void Raises_BindingValueChanged_when_collection_changed()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<ObservableCollection<object>>();\n        var wem = new Mock<IWeakEventManager>();\n\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        propertyInfo.Setup(x => x.GetValue(It.IsAny<object>(), It.IsAny<object[]>())).Returns(collection.Object);\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyCollectionChanged>(),\n                    It.IsAny<Action<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyCollectionChanged, Action<INotifyCollectionChanged, NotifyCollectionChangedEventArgs>>(\n                (sender, action) => sender.CollectionChanged += (s, a) => action((INotifyCollectionChanged)s!, a)\n            );\n\n        var hasChanged = false;\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n        binding.BindingValueChanged += (sender, args) =>\n        {\n            sender.ShouldBe(binding);\n            args.ShouldBe(EventArgs.Empty);\n            hasChanged = true;\n        };\n\n        collection.Raise(\n            x => x.CollectionChanged += null,\n            new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List<object> { new() })\n        );\n\n        hasChanged.ShouldBeTrue();\n    }\n\n    [Fact]\n    public void Raises_BindingValueChanged_when_property_changed()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n\n        var hasChanged = false;\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n        binding.BindingValueChanged += (sender, args) =>\n        {\n            sender.ShouldBe(binding);\n            args.ShouldBe(EventArgs.Empty);\n            hasChanged = true;\n        };\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(propertyName));\n\n        hasChanged.ShouldBeTrue();\n    }\n\n    [Fact]\n    public void Removes_collection_event_listener_when_property_changes_to_null()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<INotifyCollectionChanged>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        wem.Setup(\n                x => x.AddWeakEventListener(\n                    It.IsAny<INotifyPropertyChanged>(),\n                    It.IsAny<Action<INotifyPropertyChanged, PropertyChangedEventArgs>>()\n                )\n            )\n            .Callback<INotifyPropertyChanged, Action<INotifyPropertyChanged, PropertyChangedEventArgs>>(\n                (sender, action) => sender.PropertyChanged += (s, a) => action((INotifyPropertyChanged)s!, a)\n            );\n        propertyInfo.SetupSequence(x => x.GetValue(It.IsAny<INotifyPropertyChanged>(), null))\n            .Returns(collection.Object)\n            .Returns((object?)null);\n\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.Initialize();\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(propertyName));\n        wem.Verify(x => x.RemoveWeakEventListener(It.IsAny<INotifyCollectionChanged>()));\n    }\n\n    [Fact]\n    public void Should_not_raise_BindingValueChanged_on_collection_when_uninitialized()\n    {\n        const string propertyName = \"propertyName\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n        var collection = new Mock<ObservableCollection<object>>();\n        var wem = new Mock<IWeakEventManager>();\n        var propertyInfo = new Mock<PropertyInfo>();\n        propertyInfo.Setup(x => x.Name).Returns(propertyName);\n        propertyInfo.Setup(x => x.PropertyType).Returns(typeof(INotifyCollectionChanged));\n        propertyInfo.Setup(x => x.GetValue(It.IsAny<object>(), It.IsAny<object[]>())).Returns(collection.Object);\n\n        var hasChanged = false;\n        using var binding = new Binding(source.Object, propertyInfo.Object, wem.Object);\n        binding.BindingValueChanged += (_, __) => hasChanged = true;\n\n        collection.Raise(\n            x => x.CollectionChanged += null,\n            new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List<object> { new() })\n        );\n\n        hasChanged.ShouldBeFalse();\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Parameters/ParameterCacheTests.cs",
    "content": "﻿using ParameterInfo = MvvmBlazor.Internal.Parameters.ParameterInfo;\n\nnamespace MvvmBlazor.Tests.Internal.Parameters;\n\npublic class ParameterCacheTests\n{\n    [Fact]\n    public void Get_gets_cached_entry()\n    {\n        var type = typeof(ParameterCacheTests);\n        var parameterInfo = new ParameterInfo(new List<PropertyInfo>(), new List<PropertyInfo>());\n\n        var cache = new ParameterCache();\n        cache.Set(type, parameterInfo);\n\n        cache.Get(type).ShouldBeSameAs(parameterInfo);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Parameters/ParameterInfoTests.cs",
    "content": "﻿using ParameterInfo = MvvmBlazor.Internal.Parameters.ParameterInfo;\n\nnamespace MvvmBlazor.Tests.Internal.Parameters;\n\npublic class ParameterInfoTests\n{\n    private static Mock<PropertyInfo> GenerateProperty(string propertyName)\n    {\n        var property = new StrictMock<PropertyInfo>();\n        property.SetupGet(x => x.Name).Returns(propertyName);\n        property.SetupGet(x => x.DeclaringType).Returns(typeof(ParameterInfoTests));\n        property.Setup(x => x.GetHashCode()).Returns(propertyName.GetHashCode(StringComparison.OrdinalIgnoreCase));\n        property.Setup(x => x.Equals(It.IsAny<PropertyInfo>())).Returns<object?>((obj) => obj is PropertyInfo p && p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase));\n        return property;\n    }\n\n    [Fact]\n    public void Ignores_missing_property_on_viewmodel()\n    {\n        var p1 = GenerateProperty(\"p1\");\n        var p2 = GenerateProperty(\"p2\");\n        var componentProperties = new List<PropertyInfo> { p1.Object, p2.Object };\n\n        var vmp1 = GenerateProperty(\"p1\");\n        var viewModelProperties = new List<PropertyInfo> { vmp1.Object };\n\n        var info = new ParameterInfo(componentProperties, viewModelProperties);\n        info.Parameters.ShouldNotBeNull();\n        info.Parameters.Count.ShouldBe(1);\n        info.Parameters.ElementAt(0).Key.ShouldBe(p1.Object);\n        info.Parameters.ElementAt(0).Value.ShouldBe(vmp1.Object);\n    }\n\n    [Fact]\n    public void Throws_for_missing_property_on_component()\n    {\n        var p1 = GenerateProperty(\"p1\");\n        var p2 = GenerateProperty(\"p2\");\n        var componentProperties = new List<PropertyInfo> { p2.Object };\n\n        var vmp1 = GenerateProperty(\"p1\");\n        var viewModelProperties = new List<PropertyInfo> { vmp1.Object };\n\n        Should.Throw<ParameterException>(() => new ParameterInfo(componentProperties, viewModelProperties));\n    }\n\n    [Fact]\n    public void Sorts_properties()\n    {\n        var p1 = GenerateProperty(\"p1\");\n        var p2 = GenerateProperty(\"p2\");\n        var componentProperties = new List<PropertyInfo> { p1.Object, p2.Object };\n\n        var vmp1 = GenerateProperty(\"p1\");\n        var vmp2 = GenerateProperty(\"p2\");\n        var viewModelProperties = new List<PropertyInfo> { vmp2.Object, vmp1.Object };\n\n        var info = new ParameterInfo(componentProperties, viewModelProperties);\n        info.Parameters.ShouldNotBeNull();\n        info.Parameters.Count.ShouldBe(2);\n        info.Parameters.ElementAt(0).Key.ShouldBe(p1.Object);\n        info.Parameters.ElementAt(0).Value.ShouldBe(vmp1.Object);\n        info.Parameters.ElementAt(1).Key.ShouldBe(p2.Object);\n        info.Parameters.ElementAt(1).Value.ShouldBe(vmp2.Object);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Parameters/ParameterResolverTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Internal.Parameters;\n\npublic class ParameterResolverTests : UnitTest\n{\n    public ParameterResolverTests(ITestOutputHelper outputHelper) : base(outputHelper) { }\n\n    protected override void RegisterServices(IServiceCollection services)\n    {\n        services.Mock<IParameterCache>();\n        services.Provide<ParameterResolver>();\n    }\n\n    [Fact]\n    public void ResolveParameters_ignores_properties_without_attribute()\n    {\n        var resolver = Services.GetRequiredService<ParameterResolver>();\n\n        var res = resolver.ResolveParameters(typeof(S3), typeof(S3));\n        res.Parameters.Count.ShouldBe(1);\n        res.Parameters.ElementAt(0).Key.Name.ShouldBe(nameof(S3.Test));\n        res.Parameters.ElementAt(0).Key.PropertyType.ShouldBe(typeof(string));\n    }\n\n    [Fact]\n    public void ResolveParameters_ignores_properties_without_public_setter()\n    {\n        var resolver = Services.GetRequiredService<ParameterResolver>();\n\n        var res = resolver.ResolveParameters(typeof(S4), typeof(S4));\n        res.Parameters.Count.ShouldBe(1);\n        res.Parameters.ElementAt(0).Key.Name.ShouldBe(nameof(S4.Test));\n        res.Parameters.ElementAt(0).Key.PropertyType.ShouldBe(typeof(string));\n    }\n\n    [Fact]\n    public void ResolveParameters_resolves_multiple_parameters()\n    {\n        var resolver = Services.GetRequiredService<ParameterResolver>();\n\n        var res = resolver.ResolveParameters(typeof(S2), typeof(S2));\n        res.Parameters.Count.ShouldBe(2);\n        res.Parameters.ElementAt(0).Key.Name.ShouldBe(nameof(S2.Foo));\n        res.Parameters.ElementAt(0).Key.PropertyType.ShouldBe(typeof(int));\n        res.Parameters.ElementAt(1).Key.Name.ShouldBe(nameof(S2.Test));\n        res.Parameters.ElementAt(1).Key.PropertyType.ShouldBe(typeof(string));\n    }\n\n    [Fact]\n    public void ResolveParameters_resolves_single_parameter()\n    {\n        var resolver = Services.GetRequiredService<ParameterResolver>();\n\n        var res = resolver.ResolveParameters(typeof(S1), typeof(S1));\n        res.Parameters.Count.ShouldBe(1);\n        res.Parameters.ElementAt(0).Key.Name.ShouldBe(nameof(S1.Test));\n        res.Parameters.ElementAt(0).Key.PropertyType.ShouldBe(typeof(string));\n    }\n\n    [Fact]\n    public void ResolveParameters_resolves_cascading_parameter()\n    {\n        var resolver = Services.GetRequiredService<ParameterResolver>();\n\n        var res = resolver.ResolveParameters(typeof(S5), typeof(S5));\n        res.Parameters.Count.ShouldBe(1);\n        res.Parameters.ElementAt(0).Key.Name.ShouldBe(nameof(S5.Test));\n        res.Parameters.ElementAt(0).Key.PropertyType.ShouldBe(typeof(string));\n    }\n\n    private class S1\n    {\n        [Parameter] public string? Test { get; set; }\n    }\n\n    private class S2\n    {\n        [Parameter] public string? Test { get; set; }\n\n        [Parameter] public int Foo { get; set; }\n    }\n\n    private class S3\n    {\n        [Parameter] public string? Test { get; set; }\n\n        public int Foo { get; set; }\n    }\n\n    private class S4\n    {\n        [Parameter] public string? Test { get; set; }\n\n        public int Foo { get; }\n        public int Doo { get; private set; }\n        public int Boo { get; internal set; }\n        public int Loo { get; protected set; }\n        public int Moo { get; protected internal set; }\n    }\n\n    private class S5\n    {\n        [CascadingParameter] public string? Test { get; set; }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/Parameters/ViewModelParameterSetterTests.cs",
    "content": "﻿using System.Globalization;\nusing ParameterInfo = MvvmBlazor.Internal.Parameters.ParameterInfo;\n\nnamespace MvvmBlazor.Tests.Internal.Parameters;\n\npublic class ViewModelParameterSetterTests : UnitTest\n{\n    private static readonly StronglyTypedParameter TestParameter = new();\n\n    public ViewModelParameterSetterTests(ITestOutputHelper outputHelper) : base(outputHelper) { }\n\n    protected override void RegisterServices(IServiceCollection services)\n    {\n        services.StrictMock<IParameterResolver>();\n        services.StrictMock<ComponentBase>();\n        services.StrictMock<ViewModelBase>();\n        services.Provide<ViewModelParameterSetter>();\n    }\n\n    private static Mock<PropertyInfo> GenerateProperty(string propertyName, Type propertyType)\n    {\n        var property = new Mock<PropertyInfo>();\n        property.Setup(x => x.Name).Returns(propertyName).Verifiable();\n        property.SetupGet(x => x.PropertyType).Returns(propertyType).Verifiable();\n        return property;\n    }\n\n    [Fact]\n    public void ResolveAndSet_resolves_parameters_of_same_type()\n    {\n        const string propName = \"p1\";\n        const string componentValue = \"foo\";\n        var cp1 = GenerateProperty(propName, componentValue.GetType());\n        var componentProperties = new List<PropertyInfo> { cp1.Object };\n\n        var vmp1 = GenerateProperty(propName, componentValue.GetType());\n        var viewModelProperties = new List<PropertyInfo> { vmp1.Object };\n        var parameterInfo = new ParameterInfo(componentProperties, viewModelProperties);\n\n        var resolver = Services.GetMock<IParameterResolver>();\n        var component = Services.GetMock<ComponentBase>();\n        var viewModel = Services.GetMock<ViewModelBase>();\n        resolver.Setup(x => x.ResolveParameters(component.Object.GetType(), viewModel.Object.GetType()))\n            .Returns(parameterInfo)\n            .Verifiable();\n        cp1.Setup(x => x.GetValue(component.Object, null)).Returns(componentValue).Verifiable();\n        vmp1.Setup(x => x.SetValue(viewModel.Object, componentValue, null)).Verifiable();\n\n        var setter = Services.GetRequiredService<ViewModelParameterSetter>();\n\n        setter.ResolveAndSet(component.Object, viewModel.Object);\n\n        cp1.Verify();\n        vmp1.Verify();\n        resolver.Verify();\n    }\n\n    [Fact]\n    public void ResolveAndSet_resolves_parameters_of_convertible_types()\n    {\n        const string propName = \"p1\";\n        const int componentValue = 42;\n        var cp1 = GenerateProperty(propName, componentValue.GetType());\n        var componentProperties = new List<PropertyInfo> { cp1.Object };\n\n        var vmp1 = GenerateProperty(propName, typeof(StronglyTypedParameter));\n        var viewModelProperties = new List<PropertyInfo> { vmp1.Object };\n        var parameterInfo = new ParameterInfo(componentProperties, viewModelProperties);\n\n        var resolver = Services.GetMock<IParameterResolver>();\n        var component = Services.GetMock<ComponentBase>();\n        var viewModel = Services.GetMock<ViewModelBase>();\n        resolver.Setup(x => x.ResolveParameters(component.Object.GetType(), viewModel.Object.GetType()))\n            .Returns(parameterInfo)\n            .Verifiable();\n        cp1.Setup(x => x.GetValue(component.Object, null)).Returns(componentValue).Verifiable();\n        vmp1.Setup(x => x.SetValue(viewModel.Object, TestParameter, null)).Verifiable();\n\n        var setter = Services.GetRequiredService<ViewModelParameterSetter>();\n\n        setter.ResolveAndSet(component.Object, viewModel.Object);\n\n        cp1.Verify();\n        vmp1.Verify();\n        resolver.Verify();\n    }\n\n    [TypeConverter(typeof(StronglyTypedParameterConverter))]\n    private class StronglyTypedParameter { }\n\n    private class StronglyTypedParameterConverter : TypeConverter\n    {\n        public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)\n        {\n            return sourceType == typeof(int);\n        }\n\n        public override object ConvertTo(\n            ITypeDescriptorContext? context,\n            CultureInfo? culture,\n            object? value,\n            Type destinationType)\n        {\n            return TestParameter;\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/Internal/WeakEventListener/WeakEventListenerTests.cs",
    "content": "﻿namespace MvvmBlazor.Tests.Internal.WeakEventListener;\n\npublic class WeakEventManagerTests\n{\n    [Fact]\n    public void AddWeakEventListener_collection_fires_event()\n    {\n        var collectionAddObject = new object();\n        var source = new Mock<INotifyCollectionChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener(\n            source.Object,\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n                a.Action.ShouldBe(NotifyCollectionChangedAction.Add);\n                a.NewItems.ShouldNotBeNull();\n                a.NewItems.Count.ShouldBe(1);\n                a.NewItems[0].ShouldBe(collectionAddObject);\n\n                invocations++;\n            }\n        );\n\n        source.Raise(\n            x => x.CollectionChanged += null,\n            new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collectionAddObject)\n        );\n\n        invocations.ShouldBe(1);\n    }\n\n    [Fact]\n    public void AddWeakEventListener_custom_fires_event()\n    {\n        var source = new Mock<INotifyPropertyChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener<INotifyPropertyChanged, PropertyChangedEventArgs>(\n            source.Object,\n            nameof(INotifyPropertyChanged.PropertyChanged),\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n\n                invocations++;\n            }\n        );\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(\"Foo\"));\n\n        invocations.ShouldBe(1);\n    }\n\n    [Fact]\n    public void AddWeakEventListener_fires_event_after_GC()\n    {\n        var source = new Mock<INotifyPropertyChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener<INotifyPropertyChanged, PropertyChangedEventArgs>(\n            source.Object,\n            nameof(INotifyPropertyChanged.PropertyChanged),\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n\n                invocations++;\n            }\n        );\n\n        GC.Collect();\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(\"Foo\"));\n\n        invocations.ShouldBe(1);\n    }\n\n    [Fact]\n    public void AddWeakEventListener_property_fires_event()\n    {\n        const string propertyName = \"TestProperty\";\n\n        var source = new Mock<INotifyPropertyChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener(\n            source.Object,\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n                a.PropertyName.ShouldBe(propertyName);\n\n                invocations++;\n            }\n        );\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(propertyName));\n\n        invocations.ShouldBe(1);\n    }\n\n    [Fact]\n    public void ClearWeakEventListeners_event_no_longer_fires()\n    {\n        var source = new Mock<INotifyPropertyChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener<INotifyPropertyChanged, PropertyChangedEventArgs>(\n            source.Object,\n            nameof(INotifyPropertyChanged.PropertyChanged),\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n\n                invocations++;\n            }\n        );\n\n        wem.ClearWeakEventListeners();\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(\"Foo\"));\n\n        invocations.ShouldBe(0);\n    }\n\n    [Fact]\n    public void RemoveWeakEventListener_event_no_longer_fires()\n    {\n        var source = new Mock<INotifyPropertyChanged>();\n\n        var invocations = 0;\n\n        var wem = new WeakEventManager();\n        wem.AddWeakEventListener<INotifyPropertyChanged, PropertyChangedEventArgs>(\n            source.Object,\n            nameof(INotifyPropertyChanged.PropertyChanged),\n            (s, a) =>\n            {\n                s.ShouldBe(source.Object);\n\n                invocations++;\n            }\n        );\n\n        wem.RemoveWeakEventListener(source.Object);\n\n        source.Raise(x => x.PropertyChanged += null, new PropertyChangedEventArgs(\"Foo\"));\n\n        invocations.ShouldBe(0);\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/MvvmBlazor.Tests.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>net6.0</TargetFramework>\n    <IsPackable>false</IsPackable>\n  </PropertyGroup>\n\n  <ItemGroup>\n    <PackageReference Include=\"coverlet.msbuild\" Version=\"3.1.2\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n    <PackageReference Include=\"Microsoft.Extensions.DependencyInjection\" Version=\"6.0.0\" />\n    <PackageReference Include=\"Moq\" Version=\"4.16.1\" />\n    <PackageReference Include=\"Microsoft.NET.Test.Sdk\" Version=\"17.0.0\" />\n    <PackageReference Include=\"Shouldly\" Version=\"4.0.3\" />\n    <PackageReference Include=\"xunit\" Version=\"2.4.1\" />\n    <PackageReference Include=\"xunit.runner.visualstudio\" Version=\"2.4.3\">\n      <PrivateAssets>all</PrivateAssets>\n      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>\n    </PackageReference>\n  </ItemGroup>\n\n  <ItemGroup>\n    <ProjectReference Include=\"..\\MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\" />\n    <ProjectReference Include=\"..\\MvvmBlazor.Core\\MvvmBlazor.Core.csproj\" />\n  </ItemGroup>\n\n  <ItemGroup>\n    <None Update=\"xunit.runner.json\">\n      <CopyToOutputDirectory>Always</CopyToOutputDirectory>\n    </None>\n  </ItemGroup>\n\n</Project>"
  },
  {
    "path": "src/MvvmBlazor.Tests/Properties/AssemblyInfo.cs",
    "content": "﻿[assembly: CLSCompliant(false)]"
  },
  {
    "path": "src/MvvmBlazor.Tests/ViewModel/ViewModelBaseTests.cs",
    "content": "namespace MvvmBlazor.Tests.ViewModel;\n\npublic class ViewModelBaseTests\n{\n    [Fact]\n    public void Set_returns_false_on_reference_equal()\n    {\n        var obj = new object();\n        var invoked = false;\n\n        var vm = new TestViewModel();\n        vm.PropertyChanged += (_, __) => invoked = true;\n\n        var res = vm.SetProperty(ref obj, obj, \"Foo\");\n        res.ShouldBeFalse();\n\n        invoked.ShouldBeFalse();\n    }\n\n    [Fact]\n    public void Set_returns_false_on_value_equal()\n    {\n        void TestField<T>(ref T field, T value)\n        {\n            var invoked = false;\n\n            var vm = new TestViewModel();\n            vm.PropertyChanged += (_, __) => invoked = true;\n\n            var res = vm.SetProperty(ref field, value, \"Foo\");\n            res.ShouldBeFalse();\n\n            invoked.ShouldBeFalse();\n        }\n\n        var int1 = 1;\n        TestField(ref int1, 1);\n\n        var string1 = \"test\";\n        TestField(ref string1, \"test\");\n\n        var double1 = 23.3;\n        TestField(ref double1, 23.3);\n    }\n\n    [Fact]\n    public void Set_returns_true_on_value_not_equal()\n    {\n        void TestField<T>(ref T field, T value)\n        {\n            var invoked = 0;\n\n            var vm = new TestViewModel();\n            vm.PropertyChanged += (s, a) =>\n            {\n                s.ShouldBe(vm);\n                a.PropertyName.ShouldBe(\"Foo\");\n\n                invoked++;\n            };\n\n            var res = vm.SetProperty(ref field, value, \"Foo\");\n            res.ShouldBeTrue();\n\n            invoked.ShouldBe(1);\n            field.ShouldBe(value);\n        }\n\n        var int1 = 1;\n        TestField(ref int1, 2);\n\n        var string1 = \"test\";\n        TestField(ref string1, \"test1\");\n\n        var double1 = 23.3;\n        TestField(ref double1, 2.3);\n    }\n\n    [Fact]\n    public void Set_returns_False_with_custom_equality_comparer()\n    {\n        var mockEq= new StrictMock<IEqualityComparer<int>>();\n        mockEq.Setup(x => x.Equals(It.IsAny<int>(), It.IsAny<int>()))\n            .Returns(true)\n            .Verifiable();\n\n        var vm = new TestViewModel();\n        var int1 = 1;\n        var res = vm.SetProperty(ref int1, 2, mockEq.Object, \"Foo\");\n\n        res.ShouldBe(false);\n        mockEq.Verify();\n    }\n\n    [Fact]\n    public void Set_returns_true_with_custom_equality_comparer()\n    {\n        var mockEq= new StrictMock<IEqualityComparer<int>>();\n        mockEq.Setup(x => x.Equals(It.IsAny<int>(), It.IsAny<int>()))\n            .Returns(false)\n            .Verifiable();\n\n        var vm = new TestViewModel();\n        var int1 = 1;\n        var res = vm.SetProperty(ref int1, 1, mockEq.Object, \"Foo\");\n\n        res.ShouldBe(true);\n        mockEq.Verify();\n    }\n\n    private class TestViewModel : ViewModelBase\n    {\n        public bool SetProperty<T>(ref T field, T value, string? propertyName = null)\n        {\n            return Set(ref field, value, propertyName);\n        }\n\n        public bool SetProperty<T>(ref T field, T value, IEqualityComparer<T> equalityComparer, string? propertyName = null)\n        {\n            return Set(ref field, value, equalityComparer, propertyName);\n        }\n    }\n}"
  },
  {
    "path": "src/MvvmBlazor.Tests/xunit.runner.json",
    "content": "﻿{\n  \"$schema\": \"https://xunit.net/schema/current/xunit.runner.schema.json\",\n  \"methodDisplayOptions\": \"replaceUnderscoreWithSpace,useOperatorMonikers\"\n}"
  },
  {
    "path": "src/MvvmBlazor.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 16\nVisualStudioVersion = 16.0.28803.352\nMinimumVisualStudioVersion = 15.0.26124.0\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"MvvmBlazor.Core\", \"MvvmBlazor.Core\\MvvmBlazor.Core.csproj\", \"{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Items\", \"Solution Items\", \"{3454D681-0991-4626-A291-D4D9D26E91FF}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\.gitattributes = ..\\.gitattributes\n\t\t..\\.gitignore = ..\\.gitignore\n\t\t..\\.github\\workflows\\build.yaml = ..\\.github\\workflows\\build.yaml\n\t\t..\\LICENSE = ..\\LICENSE\n\t\t..\\README.md = ..\\README.md\n\t\t..\\.github\\workflows\\release.yaml = ..\\.github\\workflows\\release.yaml\n\t\t..\\.editorconfig = ..\\.editorconfig\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Samples\", \"Samples\", \"{4A4D5D8E-6CD2-4EAB-96E7-B2473C3B2925}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"MvvmBlazor.Tests\", \"MvvmBlazor.Tests\\MvvmBlazor.Tests.csproj\", \"{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorServersideSample\", \"..\\samples\\BlazorServersideSample\\BlazorServersideSample.csproj\", \"{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorSample.Components\", \"..\\samples\\BlazorSample.Components\\BlazorSample.Components.csproj\", \"{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorSample.ViewModels\", \"..\\samples\\BlazorSample.ViewModels\\BlazorSample.ViewModels.csproj\", \"{E6A464A4-911B-4AD3-9F84-9923CD4AD124}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorSample.Domain\", \"..\\samples\\BlazorSample.Domain\\BlazorSample.Domain.csproj\", \"{00E97789-4AB7-4254-BC9A-6134E16DB2B2}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Shared\", \"Shared\", \"{6F179065-0CE7-4786-9A92-5AB130D333A6}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorClientsideSample.Client\", \"..\\samples\\BlazorClientsideSample.Client\\BlazorClientsideSample.Client.csproj\", \"{0774AD8F-ADC6-4293-B456-D7B080FD17C3}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"BlazorClientsideSample.Server\", \"..\\samples\\BlazorClientsideSample.Server\\BlazorClientsideSample.Server.csproj\", \"{33D6D643-2C45-4B4B-9691-7D0D67D0E304}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"MvvmBlazor.CodeGenerators\", \"MvvmBlazor.CodeGenerators\\MvvmBlazor.CodeGenerators.csproj\", \"{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"MvvmBlazor\", \"MvvmBlazor\\MvvmBlazor.csproj\", \"{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tDebug|x64 = Debug|x64\n\t\tDebug|x86 = Debug|x86\n\t\tRelease|Any CPU = Release|Any CPU\n\t\tRelease|x64 = Release|x64\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|x64.Build.0 = Release|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{B4E1DEC6-44FF-434C-8AA9-79B3F2FE50DA}.Release|x86.Build.0 = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|x64.Build.0 = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{1D60EC2D-CA52-4AA7-AB93-CA21CB85479F}.Release|x86.Build.0 = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|x64.Build.0 = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E}.Release|x86.Build.0 = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|x64.Build.0 = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6}.Release|x86.Build.0 = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|x64.Build.0 = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124}.Release|x86.Build.0 = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|x64.Build.0 = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2}.Release|x86.Build.0 = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|x64.Build.0 = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3}.Release|x86.Build.0 = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|x64.Build.0 = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304}.Release|x86.Build.0 = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|x64.Build.0 = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{42B24F4F-5B4E-4172-9EB2-8083DFEB1042}.Release|x86.Build.0 = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|x64.ActiveCfg = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|x64.Build.0 = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|x86.ActiveCfg = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Debug|x86.Build.0 = Debug|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|x64.ActiveCfg = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|x64.Build.0 = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|x86.ActiveCfg = Release|Any CPU\n\t\t{8CE5C38E-9308-431C-BAFA-BAB3A0F1DC1C}.Release|x86.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(NestedProjects) = preSolution\n\t\t{AFAA8C8F-ACB6-41E1-B14C-6B91E074F44E} = {4A4D5D8E-6CD2-4EAB-96E7-B2473C3B2925}\n\t\t{35A25A6A-B6F2-475B-91D2-FB94E7D03FA6} = {6F179065-0CE7-4786-9A92-5AB130D333A6}\n\t\t{E6A464A4-911B-4AD3-9F84-9923CD4AD124} = {6F179065-0CE7-4786-9A92-5AB130D333A6}\n\t\t{00E97789-4AB7-4254-BC9A-6134E16DB2B2} = {6F179065-0CE7-4786-9A92-5AB130D333A6}\n\t\t{6F179065-0CE7-4786-9A92-5AB130D333A6} = {4A4D5D8E-6CD2-4EAB-96E7-B2473C3B2925}\n\t\t{0774AD8F-ADC6-4293-B456-D7B080FD17C3} = {4A4D5D8E-6CD2-4EAB-96E7-B2473C3B2925}\n\t\t{33D6D643-2C45-4B4B-9691-7D0D67D0E304} = {4A4D5D8E-6CD2-4EAB-96E7-B2473C3B2925}\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {C8D55576-3422-405F-866A-7651C879FD8E}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "src/MvvmBlazor.sln.DotSettings",
    "content": "﻿<wpf:ResourceDictionary xml:space=\"preserve\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" xmlns:s=\"clr-namespace:System;assembly=mscorlib\" xmlns:ss=\"urn:shemas-jetbrains-com:settings-storage-xaml\" xmlns:wpf=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Blazor/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Clientside/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Mvvm/@EntryIndexedValue\">True</s:Boolean>\n\t<s:Boolean x:Key=\"/Default/UserDictionary/Words/=Serverside/@EntryIndexedValue\">True</s:Boolean></wpf:ResourceDictionary>"
  }
]