├── .config
└── dotnet-tools.json
├── .editorconfig
├── .gitattributes
├── .github
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── ---support-request.md
│ ├── --bug.md
│ ├── --feature-request.md
│ └── --thank-you.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── lock.yml
├── stale.yml
├── support.yml
└── workflows
│ ├── build-and-test.yml
│ └── dependabot-auto-merge.yml
├── .gitignore
├── GitReleaseManager.yaml
├── GitVersion.yml
├── LICENSE
├── README.md
├── appveyor.yml
├── build.cake
├── build.ps1
├── cake.config
├── deployment
└── cake
│ ├── apps-uwp-tasks.cake
│ ├── apps-uwp-variables.cake
│ ├── apps-wpf-tasks.cake
│ ├── apps-wpf-variables.cake
│ ├── buildserver-continuaci.cake
│ ├── buildserver.cake
│ ├── codesigning-tasks.cake
│ ├── codesigning-variables.cake
│ ├── components-tasks.cake
│ ├── components-variables.cake
│ ├── dependencies-tasks.cake
│ ├── dependencies-variables.cake
│ ├── docker-tasks.cake
│ ├── docker-variables.cake
│ ├── generic-tasks.cake
│ ├── generic-variables.cake
│ ├── github-pages-tasks.cake
│ ├── github-pages-variables.cake
│ ├── installers-innosetup.cake
│ ├── installers-msix.cake
│ ├── installers-squirrel.cake
│ ├── installers-velopack.cake
│ ├── installers.cake
│ ├── issuetrackers-github.cake
│ ├── issuetrackers-jira.cake
│ ├── issuetrackers.cake
│ ├── lib-generic.cake
│ ├── lib-logging.cake
│ ├── lib-msbuild.cake
│ ├── lib-nuget.cake
│ ├── lib-signing.cake
│ ├── lib-sourcelink.cake
│ ├── notifications-msteams.cake
│ ├── notifications.cake
│ ├── sourcecontrol-github.cake
│ ├── sourcecontrol.cake
│ ├── tasks.cake
│ ├── templates-tasks.cake
│ ├── templates-variables.cake
│ ├── tests-nunit.cake
│ ├── tests-variables.cake
│ ├── tests.cake
│ ├── tools-tasks.cake
│ ├── tools-variables.cake
│ ├── vsextensions-tasks.cake
│ └── vsextensions-variables.cake
├── design
└── logo
│ ├── Explosion
│ ├── icon_26172.png
│ ├── icon_26172.svg
│ └── license.txt
│ ├── logo_128.png
│ ├── logo_32.png
│ └── logo_64.png
├── src
├── .vsconfig
├── Directory.Build.analyzers.props
├── Directory.Build.implicitusings.props
├── Directory.Build.nullable.props
├── Directory.Build.project.props
├── Directory.Build.props
├── Directory.Build.shared.explicit.props
├── Directory.Build.shared.implicit.props
├── Directory.Build.shared.mat.props
├── Directory.Build.shared.tests.props
├── Directory.Build.shared.tools.props
├── Directory.Build.shared.xamltools.props
├── Directory.Build.targets
├── LoadAssembliesOnStartup.Fody.TestAssembly
│ ├── DummyDependencyInjectionClass.cs
│ ├── LoadAssembliesOnStartup.Fody.TestAssembly.csproj
│ ├── Program.cs
│ └── app.config
├── LoadAssembliesOnStartup.Fody.TestAssemblyToReference
│ ├── FodyWeavers.xml
│ ├── LoadAssembliesOnStartup.Fody.TestAssemblyToReference.csproj
│ ├── ModuleInitializer.cs
│ ├── Services
│ │ ├── ClassThatShouldBeRegistered.cs
│ │ └── Interfaces
│ │ │ └── IClassThatShouldBeRegistered.cs
│ └── app.config
├── LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores
│ ├── FodyWeavers.xml
│ ├── LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.csproj
│ ├── ModuleInitializer.cs
│ ├── Services
│ │ ├── ClassThatShouldNotBeRegistered.cs
│ │ └── Interfaces
│ │ │ └── IClassThatShouldNotBeRegistered.cs
│ └── app.config
├── LoadAssembliesOnStartup.Fody.Tests
│ ├── AssemblyWeaver.cs
│ ├── ConfigurationFacts.cs
│ ├── Helpers
│ │ ├── VerifyHelper.cs
│ │ ├── WeavingFacts.ExcludesPrivateAssembliesAsync.Debug.verified.txt
│ │ ├── WeavingFacts.ExcludesPrivateAssembliesAsync.Release.verified.txt
│ │ ├── WeavingFacts.ExcludesSystemAssembliesAsync.Debug.verified.txt
│ │ ├── WeavingFacts.ExcludesSystemAssembliesAsync.Release.verified.txt
│ │ ├── WeavingFacts.HasNotRegisteredOrcFileSystemViaWildCardsAsync.Debug.verified.txt
│ │ ├── WeavingFacts.HasNotRegisteredOrcFileSystemViaWildCardsAsync.Release.verified.txt
│ │ ├── WeavingFacts.IncludesSystemAssembliesAsync.Debug.verified.txt
│ │ └── WeavingFacts.IncludesSystemAssembliesAsync.Release.verified.txt
│ ├── LoadAssembliesOnStartup.Fody.Tests.csproj
│ ├── MockAssemblyResolver.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── WeavingFacts.PrivateAssemblies.cs
│ ├── WeavingFacts.SystemAssemblies.cs
│ └── WeavingFacts.cs
├── LoadAssembliesOnStartup.Fody.sln
├── LoadAssembliesOnStartup.Fody
│ ├── AssemblyInfo.cs
│ ├── Configuration.cs
│ ├── Core
│ │ ├── MsCoreReferenceFinder.cs
│ │ ├── PrivateReference.cs
│ │ └── WeavingException.cs
│ ├── Extensions
│ │ ├── AssemblyExtensions.cs
│ │ ├── CecilExtensions.assembly.cs
│ │ ├── CecilExtensions.attributes.cs
│ │ ├── CecilExtensions.cs
│ │ ├── CecilExtensions.debuginfo.cs
│ │ ├── CecilExtensions.fields.cs
│ │ ├── CecilExtensions.members.cs
│ │ ├── CecilExtensions.methods.cs
│ │ ├── InstructionExtensions.cs
│ │ ├── InstructionListExtensions.cs
│ │ ├── ResolvingExtensions.cs
│ │ ├── StringExtensions.cs
│ │ └── TypeReferenceExtensions.cs
│ ├── FodyEnvironment.cs
│ ├── Helpers
│ │ └── CacheHelper.cs
│ ├── LoadAssembliesOnStartup.Fody.csproj
│ ├── LoadAssembliesOnStartup.Fody.props
│ ├── LoadAssembliesOnStartup.Fody.xcf
│ ├── ModuleWeaver.cs
│ └── Weaving
│ │ ├── LoadTypesWeaver.cs
│ │ ├── ModuleLoaderImporter.cs
│ │ └── ReferenceSelector.cs
├── MethodTimeLogger.cs
├── Settings.StyleCop
├── SolutionAssemblyInfo.cs
├── global.json
└── nuget.config
└── tools
└── nuget.exe
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "cake.tool": {
6 | "version": "5.0.0",
7 | "commands": [
8 | "dotnet-cake"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thanks you for your interest in contributing - Please see our our [Code of Conduct](CODE_OF_CONDUCT.md).
4 |
5 |
6 | ### Bug Fixes
7 |
8 | If you're looking for something to fix, please browse the open issues.
9 |
10 | Follow the style used by the [.NET Foundation](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md), with a few exceptions:
11 |
12 | - Apply readonly on class level private variables that are assigned in the constructor
13 | - 4 SPACES - tabs do not exist :)
14 |
15 | Read and follow our [Pull Request template](PULL_REQUEST_TEMPLATE.md) if you are submitting fixes.
16 |
17 | ### Feature Requests
18 |
19 | To propose a change or new feature, please make use the feature request area in issues.
20 |
21 | #### Non-Starter Topics
22 | The following topics should generally not be proposed for discussion as they are non-starters:
23 |
24 | * Large renames of APIs
25 | * Large non-backward-compatible breaking changes
26 | * Avoid clutter posts like "+1" which do not serve to further the conversation
27 |
28 | #### Proposal States
29 | ##### Open
30 | Open proposals are still under discussion. Please leave your concrete, constructive feedback on this proposal. +1s and other clutter posts which do not add to the discussion will be removed.
31 |
32 | ##### Accepted
33 | Accepted proposals are proposals that both the community and core team agree should be a part of projects. These proposals are ready for implementation. These proposals are available for anyone to work on unless it is already assigned to someone.
34 |
35 | If you wish to start working on an accepted proposal, please reply to the thread so we can mark you as the implementor and change the title to In Progress. This helps to avoid multiple people working on the same thing. If you decide to work on this proposal publicly, feel free to post a link to the branch as well for folks to follow along.
36 |
37 | ###### What "Accepted" does mean
38 | * Any community member is welcome to work on the idea.
39 | * The maintainers _may_ consider working on this idea on their own, but has not done so until it is marked "In Progress" with a team member assigned as the implementor.
40 | * Any pull request implementing the proposal will be welcomed with an API and code review.
41 |
42 | ###### What "Accepted" does not mean
43 | * The proposal will ever be implemented, either by a community member or maintainers.
44 | * The maintainers are committing to implementing a proposal, even if nobody else does.
45 |
46 | ##### In Progress
47 | Once a developer has begun work on a proposal, either from the team or a community member, the proposal is marked as in progress with the implementors name and (possibly) a link to a development branch to follow along with progress.
48 |
49 | #### Rejected
50 | Rejected proposals will not be implemented or merged into the code base. Once a proposal is rejected, the thread will be closed and the conversation is considered completed, pending considerable new information or changes..
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: fody
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/---support-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F62C Support Request"
3 | about: Having Trouble - ONLY contributors to other OSS projects OR people who are
4 | funding this project can submit these! If you aren't one of these, expect the ban
5 | hammer to fall
6 | title: ''
7 | labels: ''
8 | assignees: ''
9 |
10 | ---
11 |
12 | ONLY active OSS contributors OR people who buy us a coffee can ask questions here. If you don't do either of these things - DO NOT FILE HERE :)
13 |
14 | Give as much details as humanly possible if you want any sort of answer!
15 |
16 | Enter Question Below (don't delete this line)
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--bug.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F99FBug"
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: "s/unverified, t/bug \U0001F47E"
6 | assignees: ''
7 |
8 | ---
9 |
10 | # IF YOU DON'T ANSWER THIS TEMPLATE - THE BOT WILL AUTOMATICALLY CLOSE YOUR ISSUE!
11 |
12 | ## Please check all of the platforms you are having the issue on (if platform is not listed, it is not supported)
13 |
14 | - [ ] WPF
15 | - [ ] Blazor WASM
16 | - [ ] .NET Core
17 |
18 | ## Component
19 |
20 | What component is this issue occurring in?
21 |
22 | ## Version of Library
23 |
24 |
25 | ## Version of OS(s) listed above with issue
26 |
27 |
28 | ## Steps to Reproduce
29 | 1.
30 | 2.
31 | 3.
32 |
33 | ## Expected Behavior
34 |
35 |
36 | ## Actual Behavior
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F354Feature Request"
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: "s/unverified, t/enhancement \U0001F423"
6 | assignees: ''
7 |
8 | ---
9 |
10 | # IF YOU DON'T ANSWER THIS TEMPLATE - THE BOT WILL AUTOMATICALLY CLOSE YOUR ISSUE!
11 |
12 | ## Summary
13 | Please provide a brief summary of your proposal. Two to three sentences is best here.
14 |
15 | ## API Changes
16 | Include a list of all API changes, additions, subtractions as would be required by your proposal. These APIs should be considered placeholders, so the naming is not as important as getting the concepts correct. If possible you should include some "example" code of usage of your new API.
17 |
18 | ## Intended Use Case
19 | Provide a detailed example of where your proposal would be used and for what purpose.
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/--thank-you.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "❤️Thank You"
3 | about: Just want to say thank you, this is the one to do it in
4 | title: Thank You
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | Leave Your Message Below (don't delete this line though)
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Description of Change ###
2 |
3 |
4 |
5 | ### Issues Resolved ###
6 |
7 |
8 |
9 | - fixes #
10 |
11 | ### API Changes ###
12 |
13 |
14 |
15 | None
16 |
17 | ### Behavioral Changes ###
18 |
19 |
20 |
21 | None
22 |
23 | ### Testing Procedure ###
24 |
25 |
26 |
27 | ### PR Checklist ###
28 |
29 | - [ ] I have included examples or tests
30 | - [ ] I have updated the change log or created a GitHub ticket with the change
31 | - [ ] I am listed in the CONTRIBUTORS file (if it exists)
32 | - [ ] Changes adhere to coding standard
33 | - [ ] I checked the licenses of Third Party software and discussed new dependencies with at least 1 other team member
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | registries:
3 | nuget-feed-default:
4 | type: nuget-feed
5 | url: https://api.nuget.org/v3/index.json
6 |
7 | updates:
8 | - package-ecosystem: github-actions
9 | directory: "/"
10 | schedule:
11 | interval: weekly
12 |
13 | - package-ecosystem: nuget
14 | directories:
15 | - "/src"
16 | schedule:
17 | interval: daily
18 | open-pull-requests-limit: 10
19 | ignore:
20 | - dependency-name: "*Analyzers"
21 | versions:
22 | - ">= 0"
23 | registries:
24 | - nuget-feed-default
--------------------------------------------------------------------------------
/.github/lock.yml:
--------------------------------------------------------------------------------
1 | # Configuration for Lock Threads - https://github.com/dessant/lock-threads
2 |
3 | # Number of days of inactivity before a closed issue or pull request is locked
4 | daysUntilLock: 4
5 |
6 | # Skip issues and pull requests created before a given timestamp. Timestamp must
7 | # follow ISO 8601 (`YYYY-MM-DD`). Set to `false` to disable
8 | skipCreatedBefore: false
9 |
10 | # Issues and pull requests with these labels will be ignored. Set to `[]` to disable
11 | exemptLabels: ["pinned", "planned"]
12 |
13 | # Label to add before locking, such as `outdated`. Set to `false` to disable
14 | lockLabel: false
15 |
16 | # Comment to post before locking. Set to `false` to disable
17 | lockComment: >
18 | This thread has been automatically locked since there has not been
19 | any recent activity after it was closed. Please open a new issue for
20 | related bugs.
21 |
22 | # Assign `resolved` as the reason for locking. Set to `false` to disable
23 | setLockReason: true
24 |
25 | # Limit to only `issues` or `pulls`
26 | # only: issues
27 |
28 | # Optionally, specify configuration settings just for `issues` or `pulls`
29 | # issues:
30 | # exemptLabels:
31 | # - help-wanted
32 | # lockLabel: outdated
33 |
34 | # pulls:
35 | # daysUntilLock: 30
36 |
37 | # Repository to extend settings from
38 | # _extends: repo
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | - planned
10 | - nostale
11 | # Label to use when marking an issue as stale
12 | staleLabel: wontfix
13 | # Comment to post when marking an issue as stale. Set to `false` to disable
14 | markComment: >
15 | This issue has been automatically marked as stale because it has not had
16 | recent activity. It will be closed if no further activity occurs. Thank you
17 | for your contributions.
18 | # Comment to post when closing a stale issue. Set to `false` to disable
19 | closeComment: false
--------------------------------------------------------------------------------
/.github/support.yml:
--------------------------------------------------------------------------------
1 | # Configuration for Support Requests - https://github.com/dessant/support-requests
2 |
3 | # Label used to mark issues as support requests
4 | supportLabel: support
5 |
6 | # Comment to post on issues marked as support requests, `{issue-author}` is an
7 | # optional placeholder. Set to `false` to disable
8 | supportComment: >
9 | :wave: @{issue-author}, we use the issue tracker exclusively for bug reports
10 | and feature requests. However, this issue appears to be a support request.
11 | Please use our support channels to get help with the project.
12 |
13 | # Close issues marked as support requests
14 | close: true
15 |
16 | # Lock issues marked as support requests
17 | lock: false
18 |
19 | # Assign `off-topic` as the reason for locking. Set to `false` to disable
20 | setLockReason: true
21 |
22 | # Repository to extend settings from
23 | # _extends: repo
--------------------------------------------------------------------------------
/.github/workflows/build-and-test.yml:
--------------------------------------------------------------------------------
1 | name: Build and test
2 |
3 | on:
4 | push:
5 | branches:
6 | - develop
7 | - master
8 | pull_request:
9 |
10 | #permissions:
11 | #pull-requests: write
12 | #contents: write
13 |
14 | jobs:
15 | build-and-test:
16 | runs-on: windows-latest # Required for some (WPF) projects
17 |
18 | steps:
19 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
20 | id: checkout
21 | with:
22 | fetch-depth: 0
23 |
24 | - name: Setup .NET Core
25 | id: setup-dotnet
26 | uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
27 | with:
28 | dotnet-version: '9.0.x'
29 |
30 | - name: Cake Action
31 | id: cake-action
32 | uses: cake-build/cake-action@5167c3f6a9e15c76f009de2acdfb9488552bc0b9 #v3.0.0
33 | with:
34 | target: BuildAndTest
35 | arguments: |
36 | IsCiBuild: true
--------------------------------------------------------------------------------
/.github/workflows/dependabot-auto-merge.yml:
--------------------------------------------------------------------------------
1 | name: Dependabot auto-merge
2 | on: pull_request_target
3 | permissions:
4 | pull-requests: write
5 | contents: write
6 | jobs:
7 | dependabot:
8 | runs-on: ubuntu-latest
9 | # Checking the actor will prevent your Action run failing on non-Dependabot PRs
10 | if: ${{ github.actor == 'dependabot[bot]' }}
11 | steps:
12 | - name: Dependabot metadata
13 | id: dependabot-metadata
14 | uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b #2.4.0
15 | with:
16 | github-token: "${{ secrets.GITHUB_TOKEN }}"
17 | - name: Approve Dependabot PR
18 | run: gh pr review --approve "$PR_URL"
19 | env:
20 | PR_URL: ${{github.event.pull_request.html_url}}
21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 | - name: Enable auto-merge for Dependabot PRs
23 | if: |
24 | (startsWith(steps.dependabot-metadata.outputs.dependency-names, 'catel.') ||
25 | startsWith(steps.dependabot-metadata.outputs.dependency-names, 'orc.') ||
26 | startsWith(steps.dependabot-metadata.outputs.dependency-names, 'orchestra.')) &&
27 | (steps.dependabot-metadata.outputs.update-type == 'version-update:semver-minor' ||
28 | steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch')
29 | run: gh pr merge --auto --merge "$PR_URL"
30 | env:
31 | PR_URL: ${{github.event.pull_request.html_url}}
32 | PR_NUMBER: ${{github.event.pull_request.number}}
33 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | .nuget/
10 | tools/FAKE/
11 | build-log.xml
12 | Nuget.key
13 | TestResult.xml
14 |
15 | # Build results
16 | [Bb]in/
17 | [Cc]lientbin/
18 | [Dd]ebug/
19 | [Rr]elease/
20 | [Oo]utput*/
21 | [Pp]ackages*/
22 | [Tt]emp/
23 | bin
24 | obj
25 | [Ll]ib/*
26 | ![Ll]ib/repositories.config
27 | *.ide/
28 | *_i.c
29 | *_p.c
30 | *.ilk
31 | *.meta
32 | *.obj
33 | *.orig
34 | *.pch
35 | *.pdb
36 | *.pgc
37 | *.pgd
38 | *.rsp
39 | *.sbr
40 | *.tlb
41 | *.tli
42 | *.tlh
43 | *.tmp
44 | *.vspscc
45 | *.xap
46 | .builds
47 | *.log
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 |
56 | # Visual Studio profiler
57 | *.psess
58 | *.vsp
59 |
60 | # ReSharper is a .NET coding add-in
61 | _ReSharper*
62 | *.resharper.user
63 |
64 | # Catel
65 | CatelLogging.txt
66 |
67 | # Dotcover
68 | *.dotCover
69 | *.dotsettings.user
70 |
71 | # Finalbuilder
72 | *.fbl7
73 | *.fb7lck
74 | *.fbpInf
75 |
76 | # Ghostdoc
77 | *.GhostDoc.xml
78 |
79 | # Deployments
80 | deployment/FinalBuilder/backup
81 | deployment/InnoSetup/template/templates
82 | deployment/InnoSetup/template/snippets
83 | deployment/InnoSetup/template/libraries
84 | deployment/InnoSetup/template/doc
85 |
86 | # Installshield output folder
87 | [Ee]xpress
88 |
89 | # DocProject is a documentation generator add-in
90 | DocProject/buildhelp/
91 | DocProject/Help/*.HxT
92 | DocProject/Help/*.HxC
93 | DocProject/Help/*.hhc
94 | DocProject/Help/*.hhk
95 | DocProject/Help/*.hhp
96 | DocProject/Help/Html2
97 | DocProject/Help/html
98 |
99 | # Click-Once directory
100 | publish
101 |
102 | # Others
103 | [Bb]in
104 | [Oo]bj
105 | sql
106 | TestResults
107 | *.Cache
108 | ClientBin
109 | stylecop.*
110 | ~$*
111 | *.dbmdl
112 | Generated_Code #added for RIA/Silverlight projects
113 |
114 | # Backup & report files from converting an old project file to a newer
115 | # Visual Studio version. Backup files are not needed, because we have git ;-)
116 | _UpgradeReport_Files/
117 | Backup*/
118 | UpgradeLog*.XML
119 |
120 | # Windows image file caches
121 | Thumbs.db
122 |
123 | # Folder config file
124 | Desktop.ini
125 |
126 | # Cake - Uncomment if you are using it
127 | tools/**
128 | !tools/packages.config
129 | build.cakeoverrides
130 |
131 | # mstest test results
132 | TestResults
133 | .vs/
134 | .sonarqube/
135 | BundleArtifacts/
136 |
137 | # docker / tye
138 | .tye
139 |
140 | # editors
141 | .idea
142 | .vscode
143 |
144 | # Binaries
145 | *.dll
146 | *.exe
147 |
148 | # fody
149 | FodyWeavers.xsd
150 |
151 | # Approval tests
152 | *.received.*
153 |
154 | # ANTLR
155 | data/dsl/*.class
156 | data/dsl/*.java
157 |
158 | # Nodejs / NPM
159 | node_modules
160 | package-lock.json
161 |
--------------------------------------------------------------------------------
/GitReleaseManager.yaml:
--------------------------------------------------------------------------------
1 | issue-labels-include:
2 | - Breaking change
3 | - Feature
4 | - Bug
5 | - Improvement
6 | - Documentation
7 | - Dependencies
8 | issue-labels-exclude:
9 | - Build
10 | - Won't fix
11 | issue-labels-alias:
12 | - name: Documentation
13 | header: Documentation
14 | plural: Documentation
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | mode: ContinuousDeployment
2 | assembly-versioning-scheme: MajorMinorPatch
3 | next-version: 4.6.0
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 - 2018 Fody
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
LoadAssembliesOnStartup.Fody
2 |
3 | [](https://gitter.im/Fody/Fody)
4 | [](https://www.nuget.org/packages/LoadAssembliesOnStartup.Fody/)
5 |
6 | Loads all the references on startup by actually using the types in the module initializer.
7 |
8 | **See [Milestones](../../milestones?state=closed) for release notes.**
9 |
10 |
11 | ## This is an add-in for [Fody](https://github.com/Fody/Fody/)
12 |
13 | **It is expected that all developers using Fody either [become a Patron on OpenCollective](https://opencollective.com/fody/contribute/patron-3059), or have a [Tidelift Subscription](https://tidelift.com/subscription/pkg/nuget-fody?utm_source=nuget-fody&utm_medium=referral&utm_campaign=enterprise). [See Licensing/Patron FAQ](https://github.com/Fody/Home/blob/master/pages/licensing-patron-faq.md) for more information.**
14 |
15 |
16 | ### NuGet package
17 |
18 | Available here: http://nuget.org/packages/LoadAssembliesOnStartup.Fody
19 |
20 | To Install from the Nuget Package Manager Console
21 |
22 | PM> Install-Package LoadAssembliesOnStartup.Fody
23 |
24 |
25 | ## How it works
26 |
27 | By default, assemblies are only loaded on-demand. This means that the first time a type is actually used, the .NET runtime will load the assembly.
28 |
29 | When using ModuleInit, it is possible to initialize an assembly at startup. For example, to register types in a service locator.
30 |
31 | To prevent hacks such as the one displayed below:
32 |
33 | // Note: this is a hack, force loading of external assembly
34 | var dummyType = typeof(MyExternalAssemblyType);
35 | Console.WriteLine(dummyType.FullName);
36 |
37 | it is possible to let this plugin take care of this. It will add the following code for each referenced assembly that contains at least one public class:
38 |
39 | var preloadType = typeof(ReferenceType);
40 |
41 | This will ensure that an assembly is actually being loaded into the AppDomain (which is **not** the same as Assembly.LoadFrom).
42 |
43 |
44 | ## Configuration options
45 |
46 | All config options are accessible by modifying the `LoadAssembliesOnStartup` node in *FodyWeavers.xml*.
47 |
48 |
49 | ### ExcludeAssemblies
50 |
51 | A list of assembly names to exclude from the default action of "embed all Copy Local references".
52 |
53 | * Do not include `.exe` or `.dll` in the names.
54 | * Can not be defined with `IncludeAssemblies`.
55 | * Can use wildcard patterns such as `*.Tools.*`.
56 |
57 | Can take two forms.
58 |
59 | As an element with items delimited by a newline.
60 |
61 |
62 |
63 | Foo
64 | Bar
65 | Company.Tools.*
66 |
67 |
68 |
69 | Or as a attribute with items delimited by a pipe `|`.
70 |
71 |
72 |
73 |
74 | ### IncludeAssemblies
75 |
76 | A list of assembly names to include from the default action of "embed all Copy Local references".
77 |
78 | * Do not include `.exe` or `.dll` in the names.
79 | * Can not be defined with `ExcludeAssemblies`.
80 | * Can use wildcard patterns such as `*.Tools.*`.
81 |
82 | Can take two forms.
83 |
84 | As an element with items delimited by a newline.
85 |
86 |
87 |
88 | Foo
89 | Bar
90 | Company.Plugins.*
91 |
92 |
93 |
94 | Or as a attribute with items delimited by a pipe `|`.
95 |
96 |
97 |
98 |
99 | ### ExcludePrivateAssemblies
100 |
101 | Exclude private assembly references in modern SDK projects, e.g.:
102 |
103 | ```
104 |
105 | ```
106 |
107 | Types can still be excluded using the `ExcludeAssemblies` option when this option is set to `false`.
108 |
109 | The default value is `true`.
110 |
111 | To include private assemblies, use the option below:
112 |
113 |
114 |
115 |
116 | ### ExcludeSystemAssemblies
117 |
118 | Exclude system assemblies (such as System.Runtime.Serialization). Types can still be excluded using the `ExcludeAssemblies` option when this option is set to `false`.
119 |
120 | The default value is `true`.
121 |
122 | To include system assemblies, use the option below:
123 |
124 |
125 |
126 | The following wildcards will be used:
127 |
128 | - Mono.*
129 | - System.*
130 |
131 |
132 | ### ExcludeOptimizedAssemblies
133 |
134 | By default, this weaver will include references that are optimized away by the compiler. This can happen when you only use interfaces from a reference. Types can still be excluded using the `ExcludeAssemblies` option.
135 |
136 | To disable all the optimized assemblies (default .NET compiler behavior), use the option below:
137 |
138 |
139 |
140 |
141 | ### WrapInTryCatch
142 |
143 | By default, this weaver calls the `typeof(SomeType)` without any exception handling. While in general, this is good, it might happen that an assembly cannot be loaded. This can either be solved by adding it to the `ExcludeAssemblies` list *or* setting the `WrapInTryCatch` property to true:
144 |
145 |
146 |
147 | Then the weaved code will look like:
148 |
149 | try
150 | {
151 | typeof(FirstTypeFromReference1);
152 | }
153 | catch (Exception
154 | {
155 | }
156 |
157 |
158 | try
159 | {
160 | typeof(FirstTypeFromReference2);
161 | }
162 | catch (Exception
163 | {
164 | }
165 |
166 |
167 | ## Icon
168 |
169 | Explosion by Gustav Salomonsson from The Noun Project
170 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 | image: Visual Studio 2022
3 | environment:
4 | DOTNET_NOLOGO: true
5 | DOTNET_CLI_TELEMETRY_OPTOUT: true
6 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
7 | build_script:
8 | - pwsh: |
9 | Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile "./dotnet-install.ps1"
10 | ./dotnet-install.ps1 -JSonFile global.json -Architecture x64 -InstallDir 'C:\Program Files\dotnet'
11 | - dotnet build --configuration Release
12 | - dotnet test --configuration Release --no-build --no-restore
13 | test: off
14 | artifacts:
15 | - path: nugets\**\*.nupkg
--------------------------------------------------------------------------------
/build.cake:
--------------------------------------------------------------------------------
1 | //=======================================================
2 | // DEFINE PARAMETERS
3 | //=======================================================
4 |
5 | // Define the required parameters
6 | var Parameters = new Dictionary();
7 | Parameters["SolutionName"] = "LoadAssembliesOnStartup.Fody";
8 | Parameters["Company"] = "Fody";
9 | Parameters["RepositoryUrl"] = string.Format("https://github.com/{0}/{1}", GetBuildServerVariable("SolutionName"), GetBuildServerVariable("SolutionName"));
10 | Parameters["StartYear"] = "2015";
11 | Parameters["UseVisualStudioPrerelease"] = "false";
12 | Parameters["NuGet_NoDependencies"] = "false";
13 |
14 | // Note: the rest of the variables should be coming from the build server,
15 | // see `/deployment/cake/*-variables.cake` for customization options
16 | //
17 | // If required, more variables can be overridden by specifying them via the
18 | // Parameters dictionary, but the build server variables will always override
19 | // them if defined by the build server. For example, to override the code
20 | // sign wild card, add this to build.cake
21 | //
22 | // Parameters["CodeSignWildcard"] = "Orc.EntityFramework";
23 |
24 | //=======================================================
25 | // DEFINE COMPONENTS TO BUILD / PACKAGE
26 | //=======================================================
27 |
28 | Dependencies.Add("LoadAssembliesOnStartup.Fody.TestAssemblyToReference", new []
29 | {
30 | "LoadAssembliesOnStartup.Fody.TestAssembly"
31 | });
32 | Dependencies.Add("LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores", new []
33 | {
34 | "LoadAssembliesOnStartup.Fody.TestAssembly"
35 | });
36 | Dependencies.Add("LoadAssembliesOnStartup.Fody.TestAssembly");
37 |
38 | Components.Add("LoadAssembliesOnStartup.Fody");
39 |
40 | TestProjects.Add("LoadAssembliesOnStartup.Fody.Tests");
41 |
42 | //=======================================================
43 | // REQUIRED INITIALIZATION, DO NOT CHANGE
44 | //=======================================================
45 |
46 | // Now all variables are defined, include the tasks, that
47 | // script will take care of the rest of the magic
48 |
49 | #l "./deployment/cake/tasks.cake"
50 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | $ErrorActionPreference = 'Stop'
2 |
3 | Set-Location -LiteralPath $PSScriptRoot
4 |
5 | $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = '1'
6 | $env:DOTNET_CLI_TELEMETRY_OPTOUT = '1'
7 | $env:DOTNET_NOLOGO = '1'
8 |
9 | dotnet tool restore
10 | if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
11 |
12 | dotnet cake @args
13 | if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
14 |
--------------------------------------------------------------------------------
/cake.config:
--------------------------------------------------------------------------------
1 | ; The configuration file for Cake.
2 |
3 | [Settings]
4 | SkipVerification=true
5 |
6 | [Settings]
7 | EnableScriptCache=true
8 |
9 | [Paths]
10 | ; Cache=%temp%/cake-build/cache/
11 | ; Note: cache-path is set via environment variables
--------------------------------------------------------------------------------
/deployment/cake/apps-uwp-variables.cake:
--------------------------------------------------------------------------------
1 | #l "./buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class UwpContext : BuildContextWithItemsBase
6 | {
7 | public UwpContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string WindowsStoreAppId { get; set; }
13 | public string WindowsStoreClientId { get; set; }
14 | public string WindowsStoreClientSecret { get; set; }
15 | public string WindowsStoreTenantId { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' uwp projects");
24 | }
25 | }
26 |
27 | //-------------------------------------------------------------
28 |
29 | private UwpContext InitializeUwpContext(BuildContext buildContext, IBuildContext parentBuildContext)
30 | {
31 | var data = new UwpContext(parentBuildContext)
32 | {
33 | Items = UwpApps ?? new List(),
34 | WindowsStoreAppId = buildContext.BuildServer.GetVariable("WindowsStoreAppId", showValue: true),
35 | WindowsStoreClientId = buildContext.BuildServer.GetVariable("WindowsStoreClientId", showValue: false),
36 | WindowsStoreClientSecret = buildContext.BuildServer.GetVariable("WindowsStoreClientSecret", showValue: false),
37 | WindowsStoreTenantId = buildContext.BuildServer.GetVariable("WindowsStoreTenantId", showValue: false)
38 | };
39 |
40 | return data;
41 | }
42 |
43 | //-------------------------------------------------------------
44 |
45 | List _uwpApps;
46 |
47 | public List UwpApps
48 | {
49 | get
50 | {
51 | if (_uwpApps is null)
52 | {
53 | _uwpApps = new List();
54 | }
55 |
56 | return _uwpApps;
57 | }
58 | }
--------------------------------------------------------------------------------
/deployment/cake/apps-wpf-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class WpfContext : BuildContextWithItemsBase
6 | {
7 | public WpfContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 |
13 | public string DeploymentsShare { get; set; }
14 | public string Channel { get; set; }
15 | public bool AppendDeploymentChannelSuffix { get; set; }
16 | public bool UpdateDeploymentsShare { get; set; }
17 | public string AzureDeploymentsStorageConnectionString { get; set; }
18 |
19 | public bool GenerateDeploymentCatalog { get; set; }
20 | public bool GroupUpdatesByMajorVersion { get; set; }
21 | public bool DeployUpdatesToAlphaChannel { get; set; }
22 | public bool DeployUpdatesToBetaChannel { get; set; }
23 | public bool DeployUpdatesToStableChannel { get; set; }
24 | public bool DeployInstallers { get; set; }
25 |
26 | protected override void ValidateContext()
27 | {
28 |
29 | }
30 |
31 | protected override void LogStateInfoForContext()
32 | {
33 | CakeContext.Information($"Found '{Items.Count}' wpf projects");
34 |
35 | CakeContext.Information($"Generate Deployment Catalog: '{GenerateDeploymentCatalog}'");
36 | CakeContext.Information($"Group updates by major version: '{GroupUpdatesByMajorVersion}'");
37 | CakeContext.Information($"Deploy updates to alpha channel: '{DeployUpdatesToAlphaChannel}'");
38 | CakeContext.Information($"Deploy updates to beta channel: '{DeployUpdatesToBetaChannel}'");
39 | CakeContext.Information($"Deploy updates to stable channel: '{DeployUpdatesToStableChannel}'");
40 | CakeContext.Information($"Deploy installers: '{DeployInstallers}'");
41 | }
42 |
43 | public string GetDeploymentShareForProject(string projectName)
44 | {
45 | var projectSlug = GetProjectSlug(projectName, "-");
46 | var deploymentShare = System.IO.Path.Combine(DeploymentsShare, projectSlug);
47 |
48 | return deploymentShare;
49 | }
50 | }
51 |
52 | //-------------------------------------------------------------
53 |
54 | private WpfContext InitializeWpfContext(BuildContext buildContext, IBuildContext parentBuildContext)
55 | {
56 | var data = new WpfContext(parentBuildContext)
57 | {
58 | Items = WpfApps ?? new List(),
59 | DeploymentsShare = buildContext.BuildServer.GetVariable("DeploymentsShare", showValue: true),
60 | Channel = buildContext.BuildServer.GetVariable("Channel", showValue: true),
61 | AppendDeploymentChannelSuffix = buildContext.BuildServer.GetVariableAsBool("AppendDeploymentChannelSuffix", false, showValue: true),
62 | UpdateDeploymentsShare = buildContext.BuildServer.GetVariableAsBool("UpdateDeploymentsShare", true, showValue: true),
63 | AzureDeploymentsStorageConnectionString = buildContext.BuildServer.GetVariable("AzureDeploymentsStorageConnectionString"),
64 | GenerateDeploymentCatalog = buildContext.BuildServer.GetVariableAsBool("WpfGenerateDeploymentCatalog", true, showValue: true),
65 | GroupUpdatesByMajorVersion = buildContext.BuildServer.GetVariableAsBool("WpfGroupUpdatesByMajorVersion", false, showValue: true),
66 | DeployUpdatesToAlphaChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToAlphaChannel", true, showValue: true),
67 | DeployUpdatesToBetaChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToBetaChannel", true, showValue: true),
68 | DeployUpdatesToStableChannel = buildContext.BuildServer.GetVariableAsBool("WpfDeployUpdatesToStableChannel", true, showValue: true),
69 | DeployInstallers = buildContext.BuildServer.GetVariableAsBool("WpfDeployInstallers", true, showValue: true),
70 | };
71 |
72 | if (string.IsNullOrWhiteSpace(data.Channel))
73 | {
74 | data.Channel = DetermineChannel(buildContext.General);
75 |
76 | data.CakeContext.Information($"Determined channel '{data.Channel}' for wpf projects");
77 | }
78 |
79 | return data;
80 | }
81 |
82 | //-------------------------------------------------------------
83 |
84 | List _wpfApps;
85 |
86 | public List WpfApps
87 | {
88 | get
89 | {
90 | if (_wpfApps is null)
91 | {
92 | _wpfApps = new List();
93 | }
94 |
95 | return _wpfApps;
96 | }
97 | }
--------------------------------------------------------------------------------
/deployment/cake/codesigning-tasks.cake:
--------------------------------------------------------------------------------
1 | #l "codesigning-variables.cake"
2 |
3 | using System.Xml.Linq;
4 |
5 | //-------------------------------------------------------------
6 |
7 | // Empty by design for now
8 |
--------------------------------------------------------------------------------
/deployment/cake/codesigning-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class CodeSigningContext : BuildContextBase
6 | {
7 | public CodeSigningContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public List ProjectsToSignImmediately { get; set; }
13 |
14 | protected override void ValidateContext()
15 | {
16 |
17 | }
18 |
19 | protected override void LogStateInfoForContext()
20 | {
21 | //CakeContext.Information($"Found '{Items.Count}' component projects");
22 | }
23 | }
24 |
25 | //-------------------------------------------------------------
26 |
27 | private CodeSigningContext InitializeCodeSigningContext(BuildContext buildContext, IBuildContext parentBuildContext)
28 | {
29 | var data = new CodeSigningContext(parentBuildContext)
30 | {
31 | ProjectsToSignImmediately = CodeSignImmediately,
32 | };
33 |
34 | return data;
35 | }
36 |
37 | //-------------------------------------------------------------
38 |
39 | List _codeSignImmediately;
40 |
41 | public List CodeSignImmediately
42 | {
43 | get
44 | {
45 | if (_codeSignImmediately is null)
46 | {
47 | _codeSignImmediately = new List();
48 | }
49 |
50 | return _codeSignImmediately;
51 | }
52 | }
--------------------------------------------------------------------------------
/deployment/cake/components-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class ComponentsContext : BuildContextWithItemsBase
6 | {
7 | public ComponentsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string NuGetRepositoryUrl { get; set; }
13 | public string NuGetRepositoryApiKey { get; set; }
14 |
15 | protected override void ValidateContext()
16 | {
17 |
18 | }
19 |
20 | protected override void LogStateInfoForContext()
21 | {
22 | CakeContext.Information($"Found '{Items.Count}' component projects");
23 | }
24 | }
25 |
26 | //-------------------------------------------------------------
27 |
28 | private ComponentsContext InitializeComponentsContext(BuildContext buildContext, IBuildContext parentBuildContext)
29 | {
30 | var data = new ComponentsContext(parentBuildContext)
31 | {
32 | Items = Components ?? new List(),
33 | NuGetRepositoryUrl = buildContext.BuildServer.GetVariable("NuGetRepositoryUrl", showValue: true),
34 | NuGetRepositoryApiKey = buildContext.BuildServer.GetVariable("NuGetRepositoryApiKey", showValue: false)
35 | };
36 |
37 | return data;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | List _components;
43 |
44 | public List Components
45 | {
46 | get
47 | {
48 | if (_components is null)
49 | {
50 | _components = new List();
51 | }
52 |
53 | return _components;
54 | }
55 | }
--------------------------------------------------------------------------------
/deployment/cake/dependencies-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class DependenciesContext : BuildContextWithItemsBase
6 | {
7 | public DependenciesContext(IBuildContext parentBuildContext, Dictionary> dependencies)
8 | : base(parentBuildContext)
9 | {
10 | Dependencies = dependencies ?? new Dictionary>();
11 | Items = Dependencies.Keys.ToList();
12 | }
13 |
14 | public Dictionary> Dependencies { get; private set; }
15 |
16 | protected override void ValidateContext()
17 | {
18 |
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' dependency projects");
24 | }
25 |
26 | public bool ShouldBuildDependency(string dependencyProject)
27 | {
28 | return ShouldBuildDependency(dependencyProject, Array.Empty());
29 | }
30 |
31 | public bool ShouldBuildDependency(string dependencyProject, IEnumerable knownDependenciesToBeBuilt)
32 | {
33 | if (!Dependencies.TryGetValue(dependencyProject, out var dependencyInfo))
34 | {
35 | return false;
36 | }
37 |
38 | if (dependencyInfo.Count == 0)
39 | {
40 | // No explicit projects defined, always build dependency
41 | return true;
42 | }
43 |
44 | foreach (var projectRequiringDependency in dependencyInfo)
45 | {
46 | CakeContext.Information($"Checking whether '{projectRequiringDependency}' is in the list to be processed");
47 |
48 | // Check dependencies of dependencies
49 | if (knownDependenciesToBeBuilt.Any(x => string.Equals(x, projectRequiringDependency, StringComparison.OrdinalIgnoreCase)))
50 | {
51 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of dependency project '{projectRequiringDependency}', including this in the build");
52 | return true;
53 | }
54 |
55 | // Special case: *if* this is the 2nd round we check, and the project requiring this dependency is a test project,
56 | // we should check whether the test project is not already excluded. If so, the Deploy[SomeProject]Tests will return true
57 | // and this logic will still include it, so we need to exclude it explicitly
58 | if (IsTestProject((BuildContext)ParentContext, projectRequiringDependency) &&
59 | !knownDependenciesToBeBuilt.Contains(projectRequiringDependency))
60 | {
61 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of '{projectRequiringDependency}', but that is an already excluded test project, not yet including in the build");
62 |
63 | // Important: don't return, there might be other projects
64 | continue;
65 | }
66 |
67 | // Check if we should build this project
68 | if (ShouldProcessProject((BuildContext)ParentContext, projectRequiringDependency))
69 | {
70 | CakeContext.Information($"Dependency '{dependencyProject}' is a dependency of '{projectRequiringDependency}', including this in the build");
71 | return true;
72 | }
73 | }
74 |
75 | return false;
76 | }
77 | }
78 |
79 | //-------------------------------------------------------------
80 |
81 | private DependenciesContext InitializeDependenciesContext(BuildContext buildContext, IBuildContext parentBuildContext)
82 | {
83 | var data = new DependenciesContext(parentBuildContext, Dependencies);
84 |
85 | return data;
86 | }
87 |
88 | //-------------------------------------------------------------
89 |
90 | Dictionary> _dependencies;
91 |
92 | public Dictionary> Dependencies
93 | {
94 | get
95 | {
96 | if (_dependencies is null)
97 | {
98 | _dependencies = new Dictionary>();
99 | }
100 |
101 | return _dependencies;
102 | }
103 | }
--------------------------------------------------------------------------------
/deployment/cake/docker-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class DockerImagesContext : BuildContextWithItemsBase
6 | {
7 | public DockerImagesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string DockerEngineUrl { get; set; }
13 | public string DockerRegistryUrl { get; set; }
14 | public string DockerRegistryUserName { get; set; }
15 | public string DockerRegistryPassword { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | }
20 |
21 | protected override void LogStateInfoForContext()
22 | {
23 | CakeContext.Information($"Found '{Items.Count}' docker image projects");
24 | }
25 | }
26 |
27 | //-------------------------------------------------------------
28 |
29 | private DockerImagesContext InitializeDockerImagesContext(BuildContext buildContext, IBuildContext parentBuildContext)
30 | {
31 | var data = new DockerImagesContext(parentBuildContext)
32 | {
33 | Items = DockerImages ?? new List(),
34 | DockerEngineUrl = buildContext.BuildServer.GetVariable("DockerEngineUrl", showValue: true),
35 | DockerRegistryUrl = buildContext.BuildServer.GetVariable("DockerRegistryUrl", showValue: true),
36 | DockerRegistryUserName = buildContext.BuildServer.GetVariable("DockerRegistryUserName", showValue: false),
37 | DockerRegistryPassword = buildContext.BuildServer.GetVariable("DockerRegistryPassword", showValue: false)
38 | };
39 |
40 | return data;
41 | }
42 |
43 | //-------------------------------------------------------------
44 |
45 | List _dockerImages;
46 |
47 | public List DockerImages
48 | {
49 | get
50 | {
51 | if (_dockerImages is null)
52 | {
53 | _dockerImages = new List();
54 | }
55 |
56 | return _dockerImages;
57 | }
58 | }
--------------------------------------------------------------------------------
/deployment/cake/github-pages-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class GitHubPagesContext : BuildContextWithItemsBase
6 | {
7 | public GitHubPagesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string RepositoryUrl { get; set; }
13 | public string BranchName { get; set; }
14 | public string Email { get; set; }
15 | public string UserName { get; set; }
16 | public string ApiToken { get; set; }
17 |
18 | protected override void ValidateContext()
19 | {
20 | if (Items.Count == 0)
21 | {
22 | return;
23 | }
24 |
25 | if (string.IsNullOrWhiteSpace(RepositoryUrl))
26 | {
27 | throw new Exception("GitHubPagesRepositoryUrl must be defined");
28 | }
29 |
30 | if (string.IsNullOrWhiteSpace(BranchName))
31 | {
32 | throw new Exception("GitHubPagesBranchName must be defined");
33 | }
34 |
35 | if (string.IsNullOrWhiteSpace(Email))
36 | {
37 | throw new Exception("GitHubPagesEmail must be defined");
38 | }
39 |
40 | if (string.IsNullOrWhiteSpace(UserName))
41 | {
42 | throw new Exception("GitHubPagesUserName must be defined");
43 | }
44 |
45 | if (string.IsNullOrWhiteSpace(ApiToken))
46 | {
47 | throw new Exception("GitHubPagesApiToken must be defined");
48 | }
49 | }
50 |
51 | protected override void LogStateInfoForContext()
52 | {
53 | CakeContext.Information($"Found '{Items.Count}' GitHub pages projects");
54 | }
55 | }
56 |
57 | //-------------------------------------------------------------
58 |
59 | private GitHubPagesContext InitializeGitHubPagesContext(BuildContext buildContext, IBuildContext parentBuildContext)
60 | {
61 | var data = new GitHubPagesContext(parentBuildContext)
62 | {
63 | Items = GitHubPages ?? new List(),
64 | RepositoryUrl = buildContext.BuildServer.GetVariable("GitHubPagesRepositoryUrl", ((BuildContext)parentBuildContext).General.Repository.Url, showValue: true),
65 | BranchName = buildContext.BuildServer.GetVariable("GitHubPagesRepositoryUrl", "gh-pages", showValue: true),
66 | Email = buildContext.BuildServer.GetVariable("GitHubPagesEmail", showValue: true),
67 | UserName = buildContext.BuildServer.GetVariable("GitHubPagesUserName", showValue: true),
68 | ApiToken = buildContext.BuildServer.GetVariable("GitHubPagesApiToken", showValue: false),
69 | };
70 |
71 | return data;
72 | }
73 |
74 | //-------------------------------------------------------------
75 |
76 | List _gitHubPages;
77 |
78 | public List GitHubPages
79 | {
80 | get
81 | {
82 | if (_gitHubPages is null)
83 | {
84 | _gitHubPages = new List();
85 | }
86 |
87 | return _gitHubPages;
88 | }
89 | }
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers-github.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=gitreleasemanager&version=0.20.0"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class GitHubIssueTracker : IIssueTracker
6 | {
7 | public GitHubIssueTracker(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | ApiKey = buildContext.BuildServer.GetVariable("GitHubApiKey", showValue: false);
12 | OwnerName = buildContext.BuildServer.GetVariable("GitHubOwnerName", buildContext.General.Copyright.Company, showValue: true);
13 | ProjectName = buildContext.BuildServer.GetVariable("GitHubProjectName", buildContext.General.Solution.Name, showValue: true);
14 |
15 | if (!string.IsNullOrWhiteSpace(ApiKey) &&
16 | !string.IsNullOrWhiteSpace(OwnerName) &&
17 | !string.IsNullOrWhiteSpace(ProjectName))
18 | {
19 | IsAvailable = true;
20 | }
21 | }
22 |
23 | public BuildContext BuildContext { get; private set; }
24 |
25 | public string ApiKey { get; set; }
26 | public string OwnerName { get; set; }
27 | public string ProjectName { get; set; }
28 |
29 | public string OwnerAndProjectName
30 | {
31 | get { return $"{OwnerName}/{ProjectName}"; }
32 | }
33 |
34 | public bool IsAvailable { get; private set; }
35 |
36 | public async Task CreateAndReleaseVersionAsync()
37 | {
38 | if (!IsAvailable)
39 | {
40 | BuildContext.CakeContext.Information("GitHub is not available, skipping GitHub integration");
41 | return;
42 | }
43 |
44 | var version = BuildContext.General.Version.FullSemVer;
45 |
46 | BuildContext.CakeContext.Information("Releasing version '{0}' in GitHub", version);
47 |
48 | // For docs, see https://cakebuild.net/dsl/gitreleasemanager/
49 |
50 | BuildContext.CakeContext.Information("Step 1 / 4: Creating release");
51 |
52 | BuildContext.CakeContext.GitReleaseManagerCreate(ApiKey, OwnerName, ProjectName, new GitReleaseManagerCreateSettings
53 | {
54 | TargetDirectory = BuildContext.General.RootDirectory,
55 | Milestone = BuildContext.General.Version.MajorMinorPatch,
56 | Name = version,
57 | Prerelease = !BuildContext.General.IsOfficialBuild,
58 | TargetCommitish = BuildContext.General.Repository.CommitId
59 | });
60 |
61 | BuildContext.CakeContext.Information("Step 2 / 4: Adding assets to the release (not supported yet)");
62 |
63 | // Not yet supported
64 |
65 | if (!BuildContext.General.IsOfficialBuild)
66 | {
67 | BuildContext.CakeContext.Information("GitHub release publishing only runs against non-prerelease builds");
68 | }
69 | else
70 | {
71 | BuildContext.CakeContext.Information("Step 3 / 4: Publishing release");
72 |
73 | BuildContext.CakeContext.GitReleaseManagerPublish(ApiKey, OwnerName, ProjectName, BuildContext.General.Version.MajorMinorPatch, new GitReleaseManagerPublishSettings
74 | {
75 | TargetDirectory = BuildContext.General.RootDirectory
76 | });
77 |
78 | BuildContext.CakeContext.Information("Step 4 / 4: Closing the milestone");
79 |
80 | BuildContext.CakeContext.GitReleaseManagerClose(ApiKey, OwnerName, ProjectName, BuildContext.General.Version.MajorMinorPatch, new GitReleaseManagerCloseMilestoneSettings
81 | {
82 | TargetDirectory = BuildContext.General.RootDirectory
83 | });
84 | }
85 |
86 | BuildContext.CakeContext.Information("Released version in GitHub");
87 | }
88 | }
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers-jira.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=JiraCli&version=1.3.0-alpha0338&prerelease"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class JiraIssueTracker : IIssueTracker
6 | {
7 | public JiraIssueTracker(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | Url = buildContext.BuildServer.GetVariable("JiraUrl", showValue: true);
12 | Username = buildContext.BuildServer.GetVariable("JiraUsername", showValue: true);
13 | Password = buildContext.BuildServer.GetVariable("JiraPassword", showValue: false);
14 | ProjectName = buildContext.BuildServer.GetVariable("JiraProjectName", showValue: true);
15 |
16 | if (!string.IsNullOrWhiteSpace(Url) &&
17 | !string.IsNullOrWhiteSpace(ProjectName))
18 | {
19 | IsAvailable = true;
20 | }
21 | }
22 |
23 | public BuildContext BuildContext { get; private set; }
24 |
25 | public string Url { get; set; }
26 | public string Username { get; set; }
27 | public string Password { get; set; }
28 | public string ProjectName { get; set; }
29 | public bool IsAvailable { get; private set; }
30 |
31 | public async Task CreateAndReleaseVersionAsync()
32 | {
33 | if (!IsAvailable)
34 | {
35 | BuildContext.CakeContext.Information("JIRA is not available, skipping JIRA integration");
36 | return;
37 | }
38 |
39 | var version = BuildContext.General.Version.FullSemVer;
40 |
41 | BuildContext.CakeContext.Information("Releasing version '{0}' in JIRA", version);
42 |
43 | // Example call:
44 | // JiraCli.exe -url %JiraUrl% -user %JiraUsername% -pw %JiraPassword% -action createandreleaseversion
45 | // -project %JiraProjectName% -version %GitVersion_FullSemVer% -merge %IsOfficialBuild%
46 |
47 | var nugetPath = BuildContext.CakeContext.Tools.Resolve("JiraCli.exe");
48 | BuildContext.CakeContext.StartProcess(nugetPath, new ProcessSettings
49 | {
50 | Arguments = new ProcessArgumentBuilder()
51 | .AppendSwitch("-url", Url)
52 | .AppendSwitch("-user", Username)
53 | .AppendSwitchSecret("-pw", Password)
54 | .AppendSwitch("-action", "createandreleaseversion")
55 | .AppendSwitch("-project", ProjectName)
56 | .AppendSwitch("-version", version)
57 | .AppendSwitch("-merge", BuildContext.General.IsOfficialBuild.ToString())
58 | });
59 |
60 | BuildContext.CakeContext.Information("Released version in JIRA");
61 | }
62 | }
--------------------------------------------------------------------------------
/deployment/cake/issuetrackers.cake:
--------------------------------------------------------------------------------
1 | // Customize this file when using a different issue tracker
2 | #l "issuetrackers-github.cake"
3 | #l "issuetrackers-jira.cake"
4 |
5 | //-------------------------------------------------------------
6 |
7 | public interface IIssueTracker
8 | {
9 | Task CreateAndReleaseVersionAsync();
10 | }
11 |
12 | //-------------------------------------------------------------
13 |
14 | public class IssueTrackerIntegration : IntegrationBase
15 | {
16 | private readonly List _issueTrackers = new List();
17 |
18 | public IssueTrackerIntegration(BuildContext buildContext)
19 | : base(buildContext)
20 | {
21 | _issueTrackers.Add(new GitHubIssueTracker(buildContext));
22 | _issueTrackers.Add(new JiraIssueTracker(buildContext));
23 | }
24 |
25 | public async Task CreateAndReleaseVersionAsync()
26 | {
27 | BuildContext.CakeContext.LogSeparator("Creating and releasing version");
28 |
29 | foreach (var issueTracker in _issueTrackers)
30 | {
31 | try
32 | {
33 | await issueTracker.CreateAndReleaseVersionAsync();
34 | }
35 | catch (Exception ex)
36 | {
37 | BuildContext.CakeContext.Error(ex.Message);
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/deployment/cake/lib-logging.cake:
--------------------------------------------------------------------------------
1 | // Note: code originally comes from https://stackoverflow.com/questions/50826394/how-to-print-tool-command-line-in-cake
2 |
3 | ///
4 | /// Temporary sets logging verbosity.
5 | ///
6 | ///
7 | ///
8 | /// // Temporary sets logging verbosity to Diagnostic.
9 | /// using(context.UseVerbosity(Verbosity.Diagnostic))
10 | /// {
11 | /// context.DotNetBuild(project, settings);
12 | /// }
13 | ///
14 | ///
15 | public static VerbosityChanger UseVerbosity(this ICakeContext context, Verbosity newVerbosity) =>
16 | new VerbosityChanger(context.Log, newVerbosity);
17 |
18 |
19 | ///
20 | /// Temporary sets logging verbosity to Diagnostic.
21 | ///
22 | ///
23 | ///
24 | /// // Temporary sets logging verbosity to Diagnostic.
25 | /// using(context.UseDiagnosticVerbosity())
26 | /// {
27 | /// context.DotNetBuild(project, settings);
28 | /// }
29 | ///
30 | ///
31 | public static VerbosityChanger UseDiagnosticVerbosity(this ICakeContext context) =>
32 | context.UseVerbosity(Verbosity.Diagnostic);
33 |
34 | ///
35 | /// Cake log verbosity changer.
36 | /// Restores old verbosity on Dispose.
37 | ///
38 | public class VerbosityChanger : IDisposable
39 | {
40 | ICakeLog _log;
41 | Verbosity _oldVerbosity;
42 |
43 | public VerbosityChanger(ICakeLog log, Verbosity newVerbosity)
44 | {
45 | _log = log;
46 | _oldVerbosity = log.Verbosity;
47 | _log.Verbosity = newVerbosity;
48 | }
49 |
50 | public void Dispose() => _log.Verbosity = _oldVerbosity;
51 | }
--------------------------------------------------------------------------------
/deployment/cake/lib-nuget.cake:
--------------------------------------------------------------------------------
1 | public class NuGetServer
2 | {
3 | public string Url { get;set; }
4 |
5 | public string ApiKey { get;set; }
6 |
7 | public override string ToString()
8 | {
9 | var result = Url;
10 |
11 | result += string.Format(" (ApiKey present: '{0}')", !string.IsNullOrWhiteSpace(ApiKey));
12 |
13 | return result;
14 | }
15 | }
16 |
17 | //-------------------------------------------------------------
18 |
19 | public static List GetNuGetServers(string urls, string apiKeys)
20 | {
21 | var splittedUrls = urls.Split(new [] { ";" }, StringSplitOptions.None);
22 | var splittedApiKeys = apiKeys.Split(new [] { ";" }, StringSplitOptions.None);
23 |
24 | if (splittedUrls.Length != splittedApiKeys.Length)
25 | {
26 | throw new Exception("Number of api keys does not match number of urls. Even if an API key is not required, add an empty one");
27 | }
28 |
29 | var servers = new List();
30 |
31 | for (int i = 0; i < splittedUrls.Length; i++)
32 | {
33 | var url = splittedUrls[i];
34 | if (string.IsNullOrWhiteSpace(url))
35 | {
36 | throw new Exception("Url for NuGet server cannot be empty");
37 | }
38 |
39 | servers.Add(new NuGetServer
40 | {
41 | Url = url,
42 | ApiKey = splittedApiKeys[i]
43 | });
44 | }
45 |
46 | return servers;
47 | }
48 |
49 | //-------------------------------------------------------------
50 |
51 | private static void RestoreNuGetPackages(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName)
52 | {
53 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}'", solutionOrProjectFileName);
54 |
55 | var sources = SplitSeparatedList(buildContext.General.NuGet.PackageSources, ';');
56 |
57 | var runtimeIdentifiers = new []
58 | {
59 | "win-x86",
60 | "win-x64",
61 | "win-arm64",
62 | "browser-wasm"
63 | };
64 |
65 | var supportedRuntimeIdentifiers = GetProjectRuntimesIdentifiers(buildContext, solutionOrProjectFileName, runtimeIdentifiers);
66 |
67 | RestoreNuGetPackagesUsingNuGet(buildContext, solutionOrProjectFileName, sources, supportedRuntimeIdentifiers);
68 | RestoreNuGetPackagesUsingDotnetRestore(buildContext, solutionOrProjectFileName, sources, supportedRuntimeIdentifiers);
69 | }
70 |
71 | //-------------------------------------------------------------
72 |
73 | private static void RestoreNuGetPackagesUsingNuGet(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName, IReadOnlyList sources, IReadOnlyList runtimeIdentifiers)
74 | {
75 | if (!buildContext.General.NuGet.RestoreUsingNuGet)
76 | {
77 | return;
78 | }
79 |
80 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'NuGet'", solutionOrProjectFileName);
81 |
82 | // No need to deal with runtime identifiers
83 |
84 | try
85 | {
86 | var nuGetRestoreSettings = new NuGetRestoreSettings
87 | {
88 | DisableParallelProcessing = false,
89 | NoCache = false,
90 | NonInteractive = true,
91 | RequireConsent = false
92 | };
93 |
94 | if (sources.Count > 0)
95 | {
96 | nuGetRestoreSettings.Source = sources.ToList();
97 | }
98 |
99 | buildContext.CakeContext.NuGetRestore(solutionOrProjectFileName, nuGetRestoreSettings);
100 | }
101 | catch (Exception)
102 | {
103 | // Ignore
104 | }
105 | }
106 |
107 | //-------------------------------------------------------------
108 |
109 | private static void RestoreNuGetPackagesUsingDotnetRestore(BuildContext buildContext, Cake.Core.IO.FilePath solutionOrProjectFileName, IReadOnlyList sources, IReadOnlyList runtimeIdentifiers)
110 | {
111 | if (!buildContext.General.NuGet.RestoreUsingDotNetRestore)
112 | {
113 | return;
114 | }
115 |
116 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'dotnet restore'", solutionOrProjectFileName);
117 |
118 | foreach (var runtimeIdentifier in runtimeIdentifiers)
119 | {
120 | try
121 | {
122 | buildContext.CakeContext.LogSeparator("Restoring packages for '{0}' using 'dotnet restore' using runtime identifier '{1}'", solutionOrProjectFileName, runtimeIdentifier);
123 |
124 | var restoreSettings = new DotNetRestoreSettings
125 | {
126 | DisableParallel = false,
127 | Force = false,
128 | ForceEvaluate = false,
129 | IgnoreFailedSources = true,
130 | NoCache = false,
131 | NoDependencies = buildContext.General.NuGet.NoDependencies, // use true to speed up things
132 | Verbosity = DotNetVerbosity.Normal
133 | };
134 |
135 | if (!string.IsNullOrWhiteSpace(runtimeIdentifier))
136 | {
137 | buildContext.CakeContext.Information("Project restore uses explicit runtime identifier, forcing re-evaluation");
138 |
139 | restoreSettings.Force = true;
140 | restoreSettings.ForceEvaluate = true;
141 | restoreSettings.Runtime = runtimeIdentifier;
142 | }
143 |
144 | if (sources.Count > 0)
145 | {
146 | restoreSettings.Sources = sources.ToList();
147 | }
148 |
149 | using (buildContext.CakeContext.UseDiagnosticVerbosity())
150 | {
151 | buildContext.CakeContext.DotNetRestore(solutionOrProjectFileName.FullPath, restoreSettings);
152 | }
153 | }
154 | catch (Exception)
155 | {
156 | // Ignore
157 | }
158 | }
159 | }
--------------------------------------------------------------------------------
/deployment/cake/lib-sourcelink.cake:
--------------------------------------------------------------------------------
1 | public static bool IsSourceLinkSupported(BuildContext buildContext, string projectName, string projectFileName)
2 | {
3 | if (buildContext.General.SourceLink.IsDisabled)
4 | {
5 | return false;
6 | }
7 |
8 | if (buildContext.General.IsLocalBuild)
9 | {
10 | return false;
11 | }
12 |
13 | if (string.IsNullOrWhiteSpace(buildContext.General.Repository.Url))
14 | {
15 | return false;
16 | }
17 |
18 | // Only support C# projects
19 | if (!projectFileName.EndsWith(".csproj"))
20 | {
21 | return false;
22 | }
23 |
24 | // Is this a test project?
25 | if (buildContext.Tests.Items.Contains(projectName))
26 | {
27 | return false;
28 | }
29 |
30 | // Only support when running a real build, e.g. ot for 'Package' only
31 | if (!buildContext.General.Target.ToLower().Contains("build"))
32 | {
33 | return false;
34 | }
35 |
36 | return true;
37 | }
38 |
39 | //-------------------------------------------------------------
40 |
41 | public static void InjectSourceLinkInProjectFile(BuildContext buildContext, string projectName, string projectFileName)
42 | {
43 | try
44 | {
45 | // Only support C# projects
46 | if (!IsSourceLinkSupported(buildContext, projectName, projectFileName))
47 | {
48 | return;
49 | }
50 |
51 | // For SourceLink to work, the .csproj should contain something like this:
52 | //
53 | var projectFileContents = System.IO.File.ReadAllText(projectFileName);
54 | if (projectFileContents.Contains("Microsoft.SourceLink.GitHub"))
55 | {
56 | return;
57 | }
58 |
59 | buildContext.CakeContext.Warning("No SourceLink reference found, automatically injecting SourceLink package reference now");
60 |
61 | //const string MSBuildNS = (XNamespace) "http://schemas.microsoft.com/developer/msbuild/2003";
62 |
63 | var xmlDocument = XDocument.Parse(projectFileContents);
64 | var projectElement = xmlDocument.Root;
65 |
66 | // Item group with package reference
67 | var referencesItemGroup = new XElement("ItemGroup");
68 | var sourceLinkPackageReference = new XElement("PackageReference");
69 | sourceLinkPackageReference.Add(new XAttribute("Include", "Microsoft.SourceLink.GitHub"));
70 | sourceLinkPackageReference.Add(new XAttribute("Version", "1.1.1"));
71 | sourceLinkPackageReference.Add(new XAttribute("PrivateAssets", "all"));
72 |
73 | referencesItemGroup.Add(sourceLinkPackageReference);
74 | projectElement.Add(referencesItemGroup);
75 |
76 | // Item group with source root
77 | //
78 | var sourceRootItemGroup = new XElement("ItemGroup");
79 | var sourceRoot = new XElement("SourceRoot");
80 |
81 | // Required to end with a \
82 | var sourceRootValue = buildContext.General.RootDirectory;
83 | var directorySeparator = System.IO.Path.DirectorySeparatorChar.ToString();
84 | if (!sourceRootValue.EndsWith(directorySeparator))
85 | {
86 | sourceRootValue += directorySeparator;
87 | };
88 |
89 | sourceRoot.Add(new XAttribute("Include", sourceRootValue));
90 | sourceRoot.Add(new XAttribute("RepositoryUrl", buildContext.General.Repository.Url));
91 |
92 | // Note: since we are not allowing source control manager queries (we don't want to require a .git directory),
93 | // we must specify the additional information below
94 | sourceRoot.Add(new XAttribute("SourceControl", "git"));
95 | sourceRoot.Add(new XAttribute("RevisionId", buildContext.General.Repository.CommitId));
96 |
97 | sourceRootItemGroup.Add(sourceRoot);
98 | projectElement.Add(sourceRootItemGroup);
99 |
100 | xmlDocument.Save(projectFileName);
101 | }
102 | catch (Exception ex)
103 | {
104 | buildContext.CakeContext.Error($"Failed to process source link for project '{projectFileName}': {ex.Message}");
105 | }
106 | }
--------------------------------------------------------------------------------
/deployment/cake/notifications-msteams.cake:
--------------------------------------------------------------------------------
1 | #addin "nuget:?package=Cake.MicrosoftTeams&version=2.0.0"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class MsTeamsNotifier : INotifier
6 | {
7 | public MsTeamsNotifier(BuildContext buildContext)
8 | {
9 | BuildContext = buildContext;
10 |
11 | WebhookUrl = buildContext.BuildServer.GetVariable("MsTeamsWebhookUrl", showValue: false);
12 | WebhookUrlForErrors = buildContext.BuildServer.GetVariable("MsTeamsWebhookUrlForErrors", WebhookUrl, showValue: false);
13 | }
14 |
15 | public BuildContext BuildContext { get; private set; }
16 |
17 | public string WebhookUrl { get; private set; }
18 | public string WebhookUrlForErrors { get; private set; }
19 |
20 | public string GetMsTeamsWebhookUrl(string project, TargetType targetType)
21 | {
22 | // Allow per target overrides via "MsTeamsWebhookUrlFor[TargetType]"
23 | var targetTypeUrl = GetTargetSpecificConfigurationValue(BuildContext, targetType, "MsTeamsWebhookUrlFor", string.Empty);
24 | if (!string.IsNullOrEmpty(targetTypeUrl))
25 | {
26 | return targetTypeUrl;
27 | }
28 |
29 | // Allow per project overrides via "MsTeamsWebhookUrlFor[ProjectName]"
30 | var projectTypeUrl = GetProjectSpecificConfigurationValue(BuildContext, project, "MsTeamsWebhookUrlFor", string.Empty);
31 | if (!string.IsNullOrEmpty(projectTypeUrl))
32 | {
33 | return projectTypeUrl;
34 | }
35 |
36 | // Return default fallback
37 | return WebhookUrl;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | private string GetMsTeamsTarget(string project, TargetType targetType, NotificationType notificationType)
43 | {
44 | if (notificationType == NotificationType.Error)
45 | {
46 | return WebhookUrlForErrors;
47 | }
48 |
49 | return GetMsTeamsWebhookUrl(project, targetType);
50 | }
51 |
52 | //-------------------------------------------------------------
53 |
54 | public async Task NotifyAsync(string project, string message, TargetType targetType, NotificationType notificationType)
55 | {
56 | var targetWebhookUrl = GetMsTeamsTarget(project, targetType, notificationType);
57 | if (string.IsNullOrWhiteSpace(targetWebhookUrl))
58 | {
59 | return;
60 | }
61 |
62 | var messageCard = new MicrosoftTeamsMessageCard
63 | {
64 | title = project,
65 | summary = notificationType.ToString(),
66 | sections = new []
67 | {
68 | new MicrosoftTeamsMessageSection
69 | {
70 | activityTitle = notificationType.ToString(),
71 | activitySubtitle = message,
72 | activityText = " ",
73 | activityImage = "https://raw.githubusercontent.com/cake-build/graphics/master/png/cake-small.png",
74 | facts = new []
75 | {
76 | new MicrosoftTeamsMessageFacts { name ="Project", value = project },
77 | new MicrosoftTeamsMessageFacts { name ="Version", value = BuildContext.General.Version.FullSemVer },
78 | new MicrosoftTeamsMessageFacts { name ="CakeVersion", value = BuildContext.CakeContext.Environment.Runtime.CakeVersion.ToString() },
79 | //new MicrosoftTeamsMessageFacts { name ="TargetFramework", value = Context.Environment.Runtime .TargetFramework.ToString() },
80 | },
81 | }
82 | }
83 | };
84 |
85 | var result = BuildContext.CakeContext.MicrosoftTeamsPostMessage(messageCard, new MicrosoftTeamsSettings
86 | {
87 | IncomingWebhookUrl = targetWebhookUrl
88 | });
89 |
90 | if (result != System.Net.HttpStatusCode.OK)
91 | {
92 | BuildContext.CakeContext.Warning(string.Format("MsTeams result: {0}", result));
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/deployment/cake/notifications.cake:
--------------------------------------------------------------------------------
1 | #l "notifications-msteams.cake"
2 | //#l "notifications-slack.cake"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public enum NotificationType
7 | {
8 | Info,
9 |
10 | Error
11 | }
12 |
13 | //-------------------------------------------------------------
14 |
15 | public interface INotifier
16 | {
17 | Task NotifyAsync(string project, string message, TargetType targetType = TargetType.Unknown, NotificationType notificationType = NotificationType.Info);
18 | }
19 |
20 | //-------------------------------------------------------------
21 |
22 | public class NotificationsIntegration : IntegrationBase
23 | {
24 | private readonly List _notifiers = new List();
25 |
26 | public NotificationsIntegration(BuildContext buildContext)
27 | : base(buildContext)
28 | {
29 | _notifiers.Add(new MsTeamsNotifier(buildContext));
30 | }
31 |
32 | public async Task NotifyDefaultAsync(string project, string message, TargetType targetType = TargetType.Unknown)
33 | {
34 | await NotifyAsync(project, message, targetType, NotificationType.Info);
35 | }
36 |
37 | //-------------------------------------------------------------
38 |
39 | public async Task NotifyErrorAsync(string project, string message, TargetType targetType = TargetType.Unknown)
40 | {
41 | await NotifyAsync(project, string.Format("ERROR: {0}", message), targetType, NotificationType.Error);
42 | }
43 |
44 | //-------------------------------------------------------------
45 |
46 | public async Task NotifyAsync(string project, string message, TargetType targetType = TargetType.Unknown, NotificationType notificationType = NotificationType.Info)
47 | {
48 | foreach (var notifier in _notifiers)
49 | {
50 | await notifier.NotifyAsync(project, message, targetType, notificationType);
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/deployment/cake/sourcecontrol-github.cake:
--------------------------------------------------------------------------------
1 | #addin "nuget:?package=Cake.GitHub&version=1.0.0"
2 | #addin "nuget:?package=Octokit&version=14.0.0"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public class GitHubSourceControl : ISourceControl
7 | {
8 | public GitHubSourceControl(BuildContext buildContext)
9 | {
10 | BuildContext = buildContext;
11 |
12 | ApiKey = buildContext.BuildServer.GetVariable("GitHubApiKey", buildContext.General.Repository.Password, showValue: false);
13 | OwnerName = buildContext.BuildServer.GetVariable("GitHubOwnerName", buildContext.General.Copyright.Company, showValue: true);
14 | ProjectName = buildContext.BuildServer.GetVariable("GitHubProjectName", buildContext.General.Solution.Name, showValue: true);
15 |
16 | if (!string.IsNullOrWhiteSpace(ApiKey) &&
17 | !string.IsNullOrWhiteSpace(OwnerName) &&
18 | !string.IsNullOrWhiteSpace(ProjectName))
19 | {
20 | IsAvailable = true;
21 | }
22 | }
23 |
24 | public BuildContext BuildContext { get; private set; }
25 |
26 | public string ApiKey { get; set; }
27 | public string OwnerName { get; set; }
28 | public string ProjectName { get; set; }
29 |
30 | public string OwnerAndProjectName
31 | {
32 | get { return $"{OwnerName}/{ProjectName}"; }
33 | }
34 |
35 | public bool IsAvailable { get; private set; }
36 |
37 | public async Task MarkBuildAsPendingAsync(string context, string description)
38 | {
39 | UpdateStatus(GitHubStatusState.Pending, context, description);
40 | }
41 |
42 | public async Task MarkBuildAsFailedAsync(string context, string description)
43 | {
44 | UpdateStatus(GitHubStatusState.Failure, context, description);
45 | }
46 |
47 | public async Task MarkBuildAsSucceededAsync(string context, string description)
48 | {
49 | UpdateStatus(GitHubStatusState.Success, context, description);
50 | }
51 |
52 | private void UpdateStatus(GitHubStatusState state, string context, string description)
53 | {
54 | // Disabled for now
55 | return;
56 |
57 | if (!IsAvailable)
58 | {
59 | return;
60 | }
61 |
62 | BuildContext.CakeContext.Information("Updating GitHub status to '{0}' | '{1}'", state, description);
63 |
64 | var commitSha = BuildContext.General.Repository.CommitId;
65 |
66 | // Note: UserName is not really required, use string.Empty, then only api key is needed
67 | BuildContext.CakeContext.GitHubStatus(string.Empty, ApiKey, OwnerName, ProjectName, commitSha, new GitHubStatusSettings
68 | {
69 | State = state,
70 | TargetUrl = null,// "url-to-build-server",
71 | Description = description,
72 | Context = $"Cake - {context}"
73 | });
74 | }
75 | }
--------------------------------------------------------------------------------
/deployment/cake/sourcecontrol.cake:
--------------------------------------------------------------------------------
1 | // Customize this file when using a different source controls
2 | #l "sourcecontrol-github.cake"
3 |
4 | //-------------------------------------------------------------
5 |
6 | public interface ISourceControl
7 | {
8 | Task MarkBuildAsPendingAsync(string context, string description);
9 | Task MarkBuildAsFailedAsync(string context, string description);
10 | Task MarkBuildAsSucceededAsync(string context, string description);
11 | }
12 |
13 | //-------------------------------------------------------------
14 |
15 | public class SourceControlIntegration : IntegrationBase
16 | {
17 | private readonly List _sourceControls = new List();
18 |
19 | public SourceControlIntegration(BuildContext buildContext)
20 | : base(buildContext)
21 | {
22 | _sourceControls.Add(new GitHubSourceControl(buildContext));
23 | }
24 |
25 | public async Task MarkBuildAsPendingAsync(string context, string description = null)
26 | {
27 | BuildContext.CakeContext.LogSeparator($"Marking build as pending: '{description ?? string.Empty}'");
28 |
29 | context = context ?? "default";
30 | description = description ?? "Build pending";
31 |
32 | foreach (var sourceControl in _sourceControls)
33 | {
34 | try
35 | {
36 | await sourceControl.MarkBuildAsPendingAsync(context, description);
37 | }
38 | catch (Exception ex)
39 | {
40 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
41 | }
42 | }
43 | }
44 |
45 | public async Task MarkBuildAsFailedAsync(string context, string description = null)
46 | {
47 | BuildContext.CakeContext.LogSeparator($"Marking build as failed: '{description ?? string.Empty}'");
48 |
49 | context = context ?? "default";
50 | description = description ?? "Build failed";
51 |
52 | foreach (var sourceControl in _sourceControls)
53 | {
54 | try
55 | {
56 | await sourceControl.MarkBuildAsFailedAsync(context, description);
57 | }
58 | catch (Exception ex)
59 | {
60 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
61 | }
62 | }
63 | }
64 |
65 | public async Task MarkBuildAsSucceededAsync(string context, string description = null)
66 | {
67 | BuildContext.CakeContext.LogSeparator($"Marking build as succeeded: '{description ?? string.Empty}'");
68 |
69 | context = context ?? "default";
70 | description = description ?? "Build succeeded";
71 |
72 | foreach (var sourceControl in _sourceControls)
73 | {
74 | try
75 | {
76 | await sourceControl.MarkBuildAsSucceededAsync(context, description);
77 | }
78 | catch (Exception ex)
79 | {
80 | BuildContext.CakeContext.Warning($"Failed to update status: {ex.Message}");
81 | }
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/deployment/cake/templates-tasks.cake:
--------------------------------------------------------------------------------
1 | #l "templates-variables.cake"
2 |
3 | using System.Linq;
4 | using System.Text.RegularExpressions;
5 | using System.Xml.Linq;
6 | using System.IO;
7 |
8 | //-------------------------------------------------------------
9 |
10 | public class TemplatesProcessor : ProcessorBase
11 | {
12 | public TemplatesProcessor(BuildContext buildContext)
13 | : base(buildContext)
14 | {
15 | var templatesRelativePath = "./deployment/templates";
16 |
17 | if (CakeContext.DirectoryExists(templatesRelativePath))
18 | {
19 | var currentDirectoryPath = System.IO.Directory.GetCurrentDirectory();
20 | var templateAbsolutePath = System.IO.Path.Combine(currentDirectoryPath, templatesRelativePath);
21 | var files = System.IO.Directory.GetFiles(templateAbsolutePath, "*.*", System.IO.SearchOption.AllDirectories);
22 |
23 | CakeContext.Information($"Found '{files.Count()}' template files");
24 |
25 | foreach (var file in files)
26 | {
27 | BuildContext.Templates.Items.Add(file.Substring(templateAbsolutePath.Length + 1));
28 | }
29 | }
30 | }
31 |
32 | public override bool HasItems()
33 | {
34 | return BuildContext.Templates.Items.Count > 0;
35 | }
36 |
37 | public override async Task PrepareAsync()
38 | {
39 |
40 | }
41 |
42 | public override async Task UpdateInfoAsync()
43 | {
44 | if (!HasItems())
45 | {
46 | return;
47 | }
48 |
49 | var variableRegex = new Regex(@"\$\{([^}]+)\}", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Compiled);
50 |
51 | foreach (var template in BuildContext.Templates.Items)
52 | {
53 | CakeContext.Information($"Updating template file '{template}'");
54 |
55 | var templateSourceFile = $"./deployment/templates/{template}";
56 | var content = CakeContext.FileReadText(templateSourceFile);
57 |
58 | var matches = variableRegex.Matches(content);
59 |
60 | foreach (var match in matches.Cast())
61 | {
62 | var variableName = match.Groups[1].Value;
63 |
64 | CakeContext.Information($"Found usage of variable '{variableName}'");
65 |
66 | if (!BuildContext.Variables.TryGetValue(variableName, out var replacement))
67 | {
68 | CakeContext.Error($"Could not find value for variable '{variableName}'");
69 | continue;
70 | }
71 |
72 | content = content.Replace($"${{{variableName}}}", replacement);
73 | }
74 |
75 | CakeContext.FileWriteText($"{template}", content);
76 | }
77 | }
78 |
79 | public override async Task BuildAsync()
80 | {
81 | // Run templates every time
82 | await UpdateInfoAsync();
83 | }
84 |
85 | public override async Task PackageAsync()
86 | {
87 | // Run templates every time
88 | await UpdateInfoAsync();
89 | }
90 |
91 | public override async Task DeployAsync()
92 | {
93 | if (!HasItems())
94 | {
95 | return;
96 | }
97 | }
98 |
99 | public override async Task FinalizeAsync()
100 | {
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/deployment/cake/templates-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class TemplatesContext : BuildContextWithItemsBase
6 | {
7 | public TemplatesContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | protected override void ValidateContext()
13 | {
14 |
15 | }
16 |
17 | protected override void LogStateInfoForContext()
18 | {
19 | CakeContext.Information($"Found '{Items.Count}' template items");
20 | }
21 | }
22 |
23 | //-------------------------------------------------------------
24 |
25 | private TemplatesContext InitializeTemplatesContext(BuildContext buildContext, IBuildContext parentBuildContext)
26 | {
27 | var data = new TemplatesContext(parentBuildContext)
28 | {
29 | Items = Templates ?? new List(),
30 | };
31 |
32 | return data;
33 | }
34 |
35 | //-------------------------------------------------------------
36 |
37 | List _templates;
38 |
39 | public List Templates
40 | {
41 | get
42 | {
43 | if (_templates is null)
44 | {
45 | _templates = new List();
46 | }
47 |
48 | return _templates;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/deployment/cake/tests-nunit.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=NUnit.ConsoleRunner&version=3.20.1"
2 |
3 | //-------------------------------------------------------------
4 |
5 | private static void RunTestsUsingNUnit(BuildContext buildContext, string projectName, string testTargetFramework, string testResultsDirectory)
6 | {
7 | var testFile = System.IO.Path.Combine(GetProjectOutputDirectory(buildContext, projectName),
8 | testTargetFramework, $"{projectName}.dll");
9 | var resultsFile = System.IO.Path.Combine(testResultsDirectory, "testresults.xml");
10 |
11 | var nunitSettings = new NUnit3Settings
12 | {
13 | Results = new NUnit3Result[]
14 | {
15 | new NUnit3Result
16 | {
17 | FileName = resultsFile,
18 | Format = "nunit3"
19 | }
20 | },
21 | NoHeader = true,
22 | NoColor = true,
23 | NoResults = false,
24 | X86 = string.Equals(buildContext.Tests.ProcessBit, "X86", StringComparison.OrdinalIgnoreCase),
25 | Timeout = 60 * 1000, // 60 seconds
26 | Workers = 1
27 | //Work = testResultsDirectory
28 | };
29 |
30 | // Note: although the docs say you can use without array initialization, you can't
31 | buildContext.CakeContext.NUnit3(new string[] { testFile }, nunitSettings);
32 |
33 | buildContext.CakeContext.Information("Verifying whether results file '{0}' exists", resultsFile);
34 |
35 | if (!buildContext.CakeContext.FileExists(resultsFile))
36 | {
37 | throw new Exception(string.Format("Expected results file '{0}' does not exist", resultsFile));
38 | }
39 | }
--------------------------------------------------------------------------------
/deployment/cake/tests-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class TestsContext : BuildContextWithItemsBase
6 | {
7 | public TestsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string Framework { get; set; }
13 | public string TargetFramework { get; set; }
14 | public string OperatingSystem { get; set; }
15 | public string ProcessBit { get; set; }
16 |
17 | protected override void ValidateContext()
18 | {
19 | if (Items.Count == 0)
20 | {
21 | return;
22 | }
23 |
24 | if (string.IsNullOrWhiteSpace(Framework))
25 | {
26 | throw new Exception("Framework is required, specify via 'TestFramework'");
27 | }
28 |
29 | if (string.IsNullOrWhiteSpace(ProcessBit))
30 | {
31 | throw new Exception("ProcessBit is required, specify via 'TestProcessBit'");
32 | }
33 | }
34 |
35 | protected override void LogStateInfoForContext()
36 | {
37 | CakeContext.Information($"Found '{Items.Count}' test projects");
38 | }
39 | }
40 |
41 | //-------------------------------------------------------------
42 |
43 | private TestsContext InitializeTestsContext(BuildContext buildContext, IBuildContext parentBuildContext)
44 | {
45 | var data = new TestsContext(parentBuildContext)
46 | {
47 | Items = TestProjects,
48 |
49 | Framework = buildContext.BuildServer.GetVariable("TestFramework", "nunit", showValue: true),
50 | TargetFramework = buildContext.BuildServer.GetVariable("TestTargetFramework", "", showValue: true),
51 | OperatingSystem = buildContext.BuildServer.GetVariable("TestOperatingSystem", "win", showValue: true),
52 | ProcessBit = buildContext.BuildServer.GetVariable("TestProcessBit", "X64", showValue: true)
53 | };
54 |
55 | return data;
56 | }
57 |
58 | //-------------------------------------------------------------
59 |
60 | List _testProjects;
61 |
62 | public List TestProjects
63 | {
64 | get
65 | {
66 | if (_testProjects is null)
67 | {
68 | _testProjects = new List();
69 | }
70 |
71 | return _testProjects;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/deployment/cake/tools-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | //-------------------------------------------------------------
4 |
5 | public class ToolsContext : BuildContextWithItemsBase
6 | {
7 | public ToolsContext(IBuildContext parentBuildContext)
8 | : base(parentBuildContext)
9 | {
10 | }
11 |
12 | public string NuGetRepositoryUrls { get; set; }
13 | public string NuGetRepositoryApiKeys { get; set; }
14 |
15 | protected override void ValidateContext()
16 | {
17 |
18 | }
19 |
20 | protected override void LogStateInfoForContext()
21 | {
22 | CakeContext.Information($"Found '{Items.Count}' tool projects");
23 | }
24 | }
25 |
26 | //-------------------------------------------------------------
27 |
28 | private ToolsContext InitializeToolsContext(BuildContext buildContext, IBuildContext parentBuildContext)
29 | {
30 | var data = new ToolsContext(parentBuildContext)
31 | {
32 | Items = Tools ?? new List(),
33 | NuGetRepositoryUrls = buildContext.BuildServer.GetVariable("ToolsNuGetRepositoryUrls", showValue: true),
34 | NuGetRepositoryApiKeys = buildContext.BuildServer.GetVariable("ToolsNuGetRepositoryApiKeys", showValue: false)
35 | };
36 |
37 | return data;
38 | }
39 |
40 | //-------------------------------------------------------------
41 |
42 | List _tools;
43 |
44 | public List Tools
45 | {
46 | get
47 | {
48 | if (_tools is null)
49 | {
50 | _tools = new List();
51 | }
52 |
53 | return _tools;
54 | }
55 | }
--------------------------------------------------------------------------------
/deployment/cake/vsextensions-variables.cake:
--------------------------------------------------------------------------------
1 | #l "buildserver.cake"
2 |
3 | public class VsExtensionsContext : BuildContextWithItemsBase
4 | {
5 | public VsExtensionsContext(IBuildContext parentBuildContext)
6 | : base(parentBuildContext)
7 | {
8 | }
9 |
10 | public string PublisherName { get; set; }
11 | public string PersonalAccessToken { get; set; }
12 |
13 | protected override void ValidateContext()
14 | {
15 |
16 | }
17 |
18 | protected override void LogStateInfoForContext()
19 | {
20 | CakeContext.Information($"Found '{Items.Count}' vs extension projects");
21 | }
22 | }
23 |
24 | //-------------------------------------------------------------
25 |
26 | private VsExtensionsContext InitializeVsExtensionsContext(BuildContext buildContext, IBuildContext parentBuildContext)
27 | {
28 | var data = new VsExtensionsContext(parentBuildContext)
29 | {
30 | Items = VsExtensions ?? new List(),
31 | PublisherName = buildContext.BuildServer.GetVariable("VsExtensionsPublisherName", showValue: true),
32 | PersonalAccessToken = buildContext.BuildServer.GetVariable("VsExtensionsPersonalAccessToken", showValue: false),
33 | };
34 |
35 | return data;
36 | }
37 |
38 | //-------------------------------------------------------------
39 |
40 | List _vsExtensions;
41 |
42 | public List VsExtensions
43 | {
44 | get
45 | {
46 | if (_vsExtensions is null)
47 | {
48 | _vsExtensions = new List();
49 | }
50 |
51 | return _vsExtensions;
52 | }
53 | }
--------------------------------------------------------------------------------
/design/logo/Explosion/icon_26172.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fody/LoadAssembliesOnStartup/c81115bbb91f4ca9f8759628f38813e4752958eb/design/logo/Explosion/icon_26172.png
--------------------------------------------------------------------------------
/design/logo/Explosion/icon_26172.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/design/logo/Explosion/license.txt:
--------------------------------------------------------------------------------
1 | Thank you for using The Noun Project. This icon is licensed under Creative
2 | Commons Attribution and must be attributed as:
3 |
4 | Explosion by Gustav Salomonsson from The Noun Project
5 |
6 | If you have a Premium Account or have purchased a license for this icon, you
7 | don't need to worry about attribution! We will share the profits from your
8 | purchase with this icon's designer.
9 |
--------------------------------------------------------------------------------
/design/logo/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fody/LoadAssembliesOnStartup/c81115bbb91f4ca9f8759628f38813e4752958eb/design/logo/logo_128.png
--------------------------------------------------------------------------------
/design/logo/logo_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fody/LoadAssembliesOnStartup/c81115bbb91f4ca9f8759628f38813e4752958eb/design/logo/logo_32.png
--------------------------------------------------------------------------------
/design/logo/logo_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fody/LoadAssembliesOnStartup/c81115bbb91f4ca9f8759628f38813e4752958eb/design/logo/logo_64.png
--------------------------------------------------------------------------------
/src/.vsconfig:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "components": [
4 | "Microsoft.VisualStudio.Component.CoreEditor",
5 | "Microsoft.VisualStudio.Workload.CoreEditor",
6 | "Microsoft.Net.Component.4.8.SDK",
7 | "Microsoft.Net.Component.4.7.2.TargetingPack",
8 | "Microsoft.Net.ComponentGroup.DevelopmentPrerequisites",
9 | "Microsoft.VisualStudio.Component.TypeScript.TSServer",
10 | "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions",
11 | "Microsoft.VisualStudio.Component.JavaScript.TypeScript",
12 | "Microsoft.VisualStudio.Component.JavaScript.Diagnostics",
13 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
14 | "Microsoft.Component.MSBuild",
15 | "Microsoft.VisualStudio.Component.Roslyn.LanguageServices",
16 | "Microsoft.VisualStudio.Component.TextTemplating",
17 | "Component.Microsoft.VisualStudio.RazorExtension",
18 | "Microsoft.VisualStudio.Component.IISExpress",
19 | "Microsoft.VisualStudio.Component.NuGet",
20 | "Microsoft.VisualStudio.Component.MSODBC.SQL",
21 | "Microsoft.VisualStudio.Component.SQL.LocalDB.Runtime",
22 | "Microsoft.VisualStudio.Component.Common.Azure.Tools",
23 | "Microsoft.VisualStudio.Component.SQL.CLR",
24 | "Microsoft.VisualStudio.Component.MSSQL.CMDLnUtils",
25 | "Microsoft.VisualStudio.Component.ManagedDesktop.Core",
26 | "Microsoft.VisualStudio.Component.SQL.SSDT",
27 | "Microsoft.VisualStudio.Component.SQL.DataSources",
28 | "Component.Microsoft.Web.LibraryManager",
29 | "Component.Microsoft.WebTools.BrowserLink.WebLivePreview",
30 | "Microsoft.VisualStudio.ComponentGroup.Web",
31 | "Microsoft.NetCore.Component.Runtime.8.0",
32 | "Microsoft.NetCore.Component.SDK",
33 | "Microsoft.VisualStudio.Component.FSharp",
34 | "Microsoft.NetCore.Component.DevelopmentTools",
35 | "Microsoft.VisualStudio.Component.FSharp.WebTemplates",
36 | "Microsoft.VisualStudio.Component.DockerTools",
37 | "Microsoft.NetCore.Component.Web",
38 | "Microsoft.VisualStudio.Component.WebDeploy",
39 | "Microsoft.VisualStudio.Component.AppInsights.Tools",
40 | "Microsoft.VisualStudio.Component.Web",
41 | "Microsoft.VisualStudio.Component.AspNet45",
42 | "Microsoft.VisualStudio.Component.AspNet",
43 | "Component.Microsoft.VisualStudio.Web.AzureFunctions",
44 | "Microsoft.VisualStudio.ComponentGroup.AzureFunctions",
45 | "Microsoft.VisualStudio.ComponentGroup.Web.CloudTools",
46 | "Microsoft.VisualStudio.Component.DiagnosticTools",
47 | "Microsoft.VisualStudio.Component.Debugger.JustInTime",
48 | "Microsoft.VisualStudio.Component.WslDebugging",
49 | "Microsoft.VisualStudio.Workload.NetWeb",
50 | "Microsoft.VisualStudio.Component.ManagedDesktop.Prerequisites",
51 | "Microsoft.VisualStudio.Workload.ManagedDesktop"
52 | ],
53 | "extensions": []
54 | }
--------------------------------------------------------------------------------
/src/Directory.Build.analyzers.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | all
9 | runtime; build; native; contentfiles; analyzers; buildtransitive
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 | all
21 | runtime; build; native; contentfiles; analyzers; buildtransitive
22 |
23 |
24 | all
25 | runtime; build; native; contentfiles; analyzers; buildtransitive
26 |
27 |
28 |
29 |
30 |
32 | latest
33 |
34 |
35 |
46 |
47 | $(NoWarn);CA1030;CA1031;CA1054;CA1062;CA1724;CA1810;CA2007;CA2237
48 | $(NoError);CA1030;CA1031;CA1054;CA1062;CA1724;CA810;CA2007;CA2237
49 |
50 |
--------------------------------------------------------------------------------
/src/Directory.Build.implicitusings.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 |
5 |
--------------------------------------------------------------------------------
/src/Directory.Build.nullable.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | enable
4 |
5 |
--------------------------------------------------------------------------------
/src/Directory.Build.project.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | geertvanhorrik,simoncropp
8 | https://github.com/Fody/LoadAssembliesOnStartup
9 | MIT
10 | https://github.com/Fody/LoadAssembliesOnStartup
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
9 |
11 |
13 |
14 |
15 |
16 |
18 |
20 |
22 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.implicit.props:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | $(NoWarn);CA1416;CS1591;CS1998;NU1603;NU1605;NU1608;NU1701;AD0001;HAA0301;HAA0302;HAA0303;HAA0401;HAA0603
8 | $(NoError);CS1591;CS1998;NU1603;NU1605;NU1608;NU1701;AD0001;HAA0301;HAA0302;HAA0303;HAA0401;HAA0603
9 | true
10 | false
11 | true
12 | false
13 | false
14 | Release
15 | $(ProjectDir)..\..\output\$(Configuration)\
16 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb;.xml
17 | False
18 | true
19 |
20 |
21 |
22 |
26 |
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
34 | latest
35 |
36 |
37 |
38 |
40 | portable
41 |
42 | true
43 |
44 |
45 |
46 |
48 | portable
49 | true
50 |
51 |
52 |
53 |
55 | portable
56 | true
57 |
58 |
59 |
60 |
61 |
62 | direct
63 |
64 | low
65 |
66 |
67 |
68 |
69 | true
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.mat.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | 4.0
10 | en-US
11 | true
12 | true
13 | true
14 |
15 |
16 |
17 | <_ResxFiles Remove="Properties\*.resx" />
18 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.tests.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | false
10 | true
11 | true
12 |
13 |
14 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.tools.props:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | $(Description)
10 | $(PackageProjectUrl)
11 | IncludeDefaultProjectBuildOutputInPack
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | $([MSBuild]::MakeRelative('$(OutputPath)\$(TargetFrameworks)\', %(ToolDllFiles.FullPath)))
31 | tools
32 |
33 |
34 |
35 | $([MSBuild]::MakeRelative('$(OutputPath)\$(TargetFrameworks)\', %(ToolExeFiles.FullPath)))
36 | tools
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/Directory.Build.shared.xamltools.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | false
35 |
36 |
37 |
38 | true
39 |
40 |
41 |
42 |
43 | False
44 | False
45 | False
46 |
47 |
48 |
49 |
50 | True
51 |
52 |
53 |
54 |
55 | False
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
66 |
67 |
68 |
69 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssembly/DummyDependencyInjectionClass.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssembly
2 | {
3 | using TestAssemblyToReference.Services;
4 |
5 | public class DummyDependencyInjectionClass
6 | {
7 | #region Constructors
8 | public DummyDependencyInjectionClass(IClassThatShouldBeRegistered classThatShouldBeRegistered)
9 | {
10 | }
11 | #endregion
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssembly/LoadAssembliesOnStartup.Fody.TestAssembly.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | LoadAssembliesOnStartup.Fody.TestAssembly
5 | LoadAssembliesOnStartup.Fody.TestAssembly
6 | en-US
7 | LoadAssembliesOnStartup.Fody.TestAssembly
8 | 1.0.0-alpha0001
9 | LoadAssembliesOnStartup.Fody.TestAssembly library.
10 |
11 | true
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssembly/Program.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssembly
2 | {
3 | using System;
4 | using Catel.IoC;
5 | using Orc.FileSystem;
6 | using TestAssemblyToReference.Services;
7 | using TestAssemblyToReferenceWithIgnores.Services;
8 |
9 | public class Program
10 | {
11 | #region Methods
12 |
13 | public static void MyFileSystemTest()
14 | {
15 | var typeToLoad = typeof(Orc.FileSystem.DirectoryService);
16 |
17 | #if !DEBUG
18 | Console.WriteLine(typeToLoad);
19 | #endif
20 | }
21 |
22 | public static void ExampleCallForIlInspection()
23 | {
24 | //Debug.WriteLine("Loading assembly TestAssemblyToReference");
25 | var typeToLoad1 = typeof(ClassThatShouldBeRegistered);
26 |
27 | #if !DEBUG
28 | Console.WriteLine(typeToLoad1);
29 | #endif
30 | }
31 |
32 | public static void ExampleCallForIlInspectionWithTryCatch()
33 | {
34 | try
35 | {
36 | //Debug.WriteLine("Loading assembly TestAssemblyToReference");
37 | var typeToLoad1 = typeof(ClassThatShouldBeRegistered);
38 |
39 | #if !DEBUG
40 | Console.WriteLine(typeToLoad1);
41 | #endif
42 | }
43 | catch (Exception)
44 | {
45 | }
46 |
47 | try
48 | {
49 | //Debug.WriteLine("Loading assembly TestAssemblyToReference");
50 | var typeToLoad2 = typeof(ClassThatShouldBeRegistered);
51 |
52 | #if !DEBUG
53 | Console.WriteLine(typeToLoad2);
54 | #endif
55 | }
56 | catch (Exception)
57 | {
58 | }
59 | }
60 | #endregion
61 |
62 | public static bool IsRightAssemblyLoaded { get { return ServiceLocator.Default.IsTypeRegistered(); } }
63 | public static bool IsRightAssemblyUnloaded { get { return ServiceLocator.Default.IsTypeRegistered(); } }
64 | public static bool IsOrcFileSystemLoaded { get { return ServiceLocator.Default.IsTypeRegistered(); } }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssembly/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/LoadAssembliesOnStartup.Fody.TestAssemblyToReference.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | LoadAssembliesOnStartup.Fody.TestAssemblyToReference
5 | LoadAssembliesOnStartup.Fody.TestAssemblyToReference
6 | en-US
7 | LoadAssembliesOnStartup.Fody.TestAssemblyToReference
8 | 1.0.0-alpha0001
9 | LoadAssembliesOnStartup.Fody.TestAssemblyToReference library.
10 |
11 | true
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using Catel.IoC;
2 | using LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services;
3 |
4 | ///
5 | /// Used by the ModuleInit. All code inside the Initialize method is ran as soon as the assembly is loaded.
6 | ///
7 | public static class ModuleInitializer
8 | {
9 | ///
10 | /// Initializes the module.
11 | ///
12 | public static void Initialize()
13 | {
14 | var serviceLocator = ServiceLocator.Default;
15 |
16 | serviceLocator.RegisterType();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/Services/ClassThatShouldBeRegistered.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services
2 | {
3 | public class ClassThatShouldBeRegistered : IClassThatShouldBeRegistered
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/Services/Interfaces/IClassThatShouldBeRegistered.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services
2 | {
3 | public interface IClassThatShouldBeRegistered
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReference/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores
5 | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores
6 | en-US
7 | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores
8 | 1.0.0-alpha0001
9 | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores library.
10 |
11 | true
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/ModuleInitializer.cs:
--------------------------------------------------------------------------------
1 | using Catel.IoC;
2 | using LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services;
3 |
4 | ///
5 | /// Used by the ModuleInit. All code inside the Initialize method is ran as soon as the assembly is loaded.
6 | ///
7 | public static class ModuleInitializer
8 | {
9 | ///
10 | /// Initializes the module.
11 | ///
12 | public static void Initialize()
13 | {
14 | var serviceLocator = ServiceLocator.Default;
15 |
16 | serviceLocator.RegisterType();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/Services/ClassThatShouldNotBeRegistered.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services
2 | {
3 | public class ClassThatShouldNotBeRegistered : IClassThatShouldNotBeRegistered
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/Services/Interfaces/IClassThatShouldNotBeRegistered.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services
2 | {
3 | public interface IClassThatShouldNotBeRegistered
4 | {
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/AssemblyWeaver.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Xml.Linq;
5 | using Catel.Reflection;
6 | using LoadAssembliesOnStartup.Fody;
7 | using LoadAssembliesOnStartup.Fody.TestAssembly;
8 | using Mono.Cecil;
9 | using Fody;
10 |
11 | public class AssemblyWeaver
12 | {
13 | private readonly Dictionary _assemblies = new Dictionary();
14 |
15 | static AssemblyWeaver()
16 | {
17 | Instance = new AssemblyWeaver();
18 | }
19 |
20 | public AssemblyWeaver(List referenceAssemblyPaths = null)
21 | {
22 | if (referenceAssemblyPaths is null)
23 | {
24 | referenceAssemblyPaths = new List();
25 | }
26 | }
27 |
28 | public TestResult GetAssembly(string testCaseName, string configString)
29 | {
30 | if (!_assemblies.ContainsKey(configString))
31 | {
32 | var type = typeof(DummyDependencyInjectionClass);
33 |
34 | var assemblyPath = type.GetAssemblyEx().Location;
35 |
36 | var rootDirectory = Directory.GetParent(assemblyPath).FullName;
37 | var testCaseDirectory = Path.Combine(rootDirectory, testCaseName);
38 | Directory.CreateDirectory(testCaseDirectory);
39 |
40 | var assemblyResolver = new TestAssemblyResolver();
41 | //assemblyResolver.AddSearchDirectory(testCaseDirectory);
42 | //assemblyResolver.AddSearchDirectory(rootDirectory);
43 |
44 | var metadataResolver = new MetadataResolver(assemblyResolver);
45 |
46 | var readerParameters = new ReaderParameters
47 | {
48 | AssemblyResolver = assemblyResolver,
49 | MetadataResolver = metadataResolver,
50 | ReadSymbols = false,
51 | };
52 |
53 | using (var moduleDefinition = ModuleDefinition.ReadModule(assemblyPath, readerParameters))
54 | {
55 | // Important note: the test project can be on a completely different location (especially on a build agent)
56 | var projectName = Path.GetFileName(assemblyPath).Replace(".dll", string.Empty);
57 |
58 | // Check 1: fixed location from test
59 | var relativeCsProjectFilePath = Path.Combine(Directory.GetParent(assemblyPath).FullName, "..", "..", "..", "..", "src", projectName, $"{projectName}.csproj");
60 | var csProjectFilePath = Path.GetFullPath(relativeCsProjectFilePath);
61 |
62 | if (!File.Exists(csProjectFilePath))
63 | {
64 | // Check 2: Check 2 directories up, then search for the project file (happens on a build agent)
65 | var searchDirectory = Path.Combine(Directory.GetParent(assemblyPath).FullName, "..", "..", "..", "Source");
66 | var searchFileName = $"{projectName}.csproj";
67 | csProjectFilePath = Directory.GetFiles(searchDirectory, searchFileName, SearchOption.AllDirectories).FirstOrDefault();
68 | }
69 |
70 | if (!File.Exists(csProjectFilePath))
71 | {
72 | throw new System.Exception($"Project file '{csProjectFilePath}' does not exist, make sure to check the paths since this is required for the unit tests");
73 | }
74 |
75 | var references = new string[]
76 | {
77 | //"Catel.Core.dll",
78 | //"Orc.FileSystem.dll"
79 | };
80 |
81 | var weaver = new ModuleWeaver
82 | {
83 | Config = XElement.Parse(configString),
84 | AssemblyResolver = assemblyResolver,
85 | ProjectFilePath = csProjectFilePath,
86 | ModuleDefinition = moduleDefinition,
87 | References = string.Join(";", references.Select(r => Path.Combine(rootDirectory, r))),
88 | ReferenceCopyLocalPaths = references.Select(r => Path.Combine(rootDirectory, r)).ToList(),
89 | };
90 |
91 | var testResult = weaver.ExecuteTestRun(assemblyPath,
92 | assemblyName: testCaseName,
93 | ignoreCodes: new[] { "0x80131869" },
94 | runPeVerify: false);
95 |
96 | if (testResult.Errors.Count > 0)
97 | {
98 | throw new System.Exception("Received errors while weaving");
99 | }
100 |
101 | _assemblies[configString] = testResult;
102 | }
103 | }
104 |
105 | return _assemblies[configString];
106 | }
107 |
108 | public static AssemblyWeaver Instance { get; private set; }
109 | }
110 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/ConfigurationFacts.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Tests
2 | {
3 | using System.Xml.Linq;
4 | using Fody;
5 | using NUnit.Framework;
6 |
7 | [TestFixture]
8 | public class ConfigurationFacts
9 | {
10 | [TestCase]
11 | public void ExcludeAssembliesNode()
12 | {
13 | var xElement = XElement.Parse(@"
14 |
15 |
16 | Foo
17 | Bar
18 | Company.Tools.*
19 |
20 | ");
21 | var config = new Configuration(xElement);
22 |
23 | Assert.That(config.ExcludeAssemblies[0], Is.EqualTo("Foo"));
24 | Assert.That(config.ExcludeAssemblies[1], Is.EqualTo("Bar"));
25 | Assert.That(config.ExcludeAssemblies[2], Is.EqualTo("Company.Tools.*"));
26 | }
27 |
28 | [TestCase]
29 | public void ExcludeAssembliesAttribute()
30 | {
31 | var xElement = XElement.Parse(@"
32 | ");
33 | var config = new Configuration(xElement);
34 |
35 | Assert.That(config.ExcludeAssemblies[0], Is.EqualTo("Foo"));
36 | Assert.That(config.ExcludeAssemblies[1], Is.EqualTo("Bar"));
37 | Assert.That(config.ExcludeAssemblies[2], Is.EqualTo("Company.Tools.*"));
38 | }
39 |
40 | [TestCase]
41 | public void ExcludeAssembliesCombined()
42 | {
43 | var xElement = XElement.Parse(@"
44 |
45 |
46 | Bar
47 |
48 | ");
49 | var config = new Configuration(xElement);
50 |
51 | Assert.That(config.ExcludeAssemblies[0], Is.EqualTo("Foo"));
52 | Assert.That(config.ExcludeAssemblies[1], Is.EqualTo("Bar"));
53 | }
54 |
55 | [TestCase]
56 | public void IncludeAssembliesNode()
57 | {
58 | var xElement = XElement.Parse(@"
59 |
60 |
61 | Foo
62 | Bar
63 | Company.Tools.*
64 |
65 | ");
66 | var config = new Configuration(xElement);
67 |
68 | Assert.That(config.IncludeAssemblies[0], Is.EqualTo("Foo"));
69 | Assert.That(config.IncludeAssemblies[1], Is.EqualTo("Bar"));
70 | Assert.That(config.IncludeAssemblies[2], Is.EqualTo("Company.Tools.*"));
71 | }
72 |
73 | [TestCase]
74 | public void IncludeAssembliesAttribute()
75 | {
76 | var xElement = XElement.Parse(@"
77 | ");
78 | var config = new Configuration(xElement);
79 |
80 | Assert.That(config.IncludeAssemblies[0], Is.EqualTo("Foo"));
81 | Assert.That(config.IncludeAssemblies[1], Is.EqualTo("Bar"));
82 | Assert.That(config.IncludeAssemblies[2], Is.EqualTo("Company.Tools.*"));
83 | }
84 |
85 | [TestCase]
86 | public void IncludeAndExcludeAssembliesAttribute()
87 | {
88 | var xElement = XElement.Parse(@"
89 | ");
90 |
91 | Assert.Throws(() => new Configuration(xElement));
92 | }
93 |
94 | [TestCase]
95 | public void IncludeAssembliesCombined()
96 | {
97 | var xElement = XElement.Parse(@"
98 |
99 |
100 | Bar
101 |
102 | ");
103 | var config = new Configuration(xElement);
104 |
105 | Assert.That(config.IncludeAssemblies[0], Is.EqualTo("Foo"));
106 | Assert.That(config.IncludeAssemblies[1], Is.EqualTo("Bar"));
107 | }
108 |
109 | [TestCase]
110 | public void ExcludeSystemAssemblies()
111 | {
112 | var xElement = XElement.Parse(@"
113 | ");
114 |
115 | var config = new Configuration(xElement);
116 |
117 | Assert.That(config.ExcludeSystemAssemblies, Is.False);
118 | }
119 |
120 | [TestCase]
121 | public void ExcludePrivateAssemblies()
122 | {
123 | var xElement = XElement.Parse(@"
124 | ");
125 |
126 | var config = new Configuration(xElement);
127 |
128 | Assert.That(config.ExcludePrivateAssemblies, Is.False);
129 | }
130 |
131 | [TestCase]
132 | public void ExcludeOptimizedAssemblies()
133 | {
134 | var xElement = XElement.Parse(@"
135 | ");
136 |
137 | var config = new Configuration(xElement);
138 |
139 | Assert.That(config.ExcludeOptimizedAssemblies, Is.True);
140 | }
141 |
142 | [TestCase]
143 | public void WrapInTryCatch()
144 | {
145 | var xElement = XElement.Parse(@"
146 | ");
147 |
148 | var config = new Configuration(xElement);
149 |
150 | Assert.That(config.WrapInTryCatch, Is.True);
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/VerifyHelper.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Tests
2 | {
3 | using System.Linq;
4 | using System.Runtime.CompilerServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Catel;
8 | using Catel.Reflection;
9 | using Microsoft.Win32.SafeHandles;
10 | using Mono.Cecil;
11 | using Mono.Cecil.Rocks;
12 | using VerifyNUnit;
13 | using VerifyTests;
14 |
15 | public static class VerifyHelper
16 | {
17 | static VerifyHelper()
18 | {
19 | }
20 |
21 | [MethodImpl(MethodImplOptions.NoInlining)]
22 | public static async Task AssertIlCodeAsync(string assemblyFileName, [CallerMemberName]string callerMemberName = "")
23 | {
24 | var slug = callerMemberName.GetSlug();
25 |
26 | var assemblyDefinition = AssemblyDefinition.ReadAssembly(assemblyFileName);
27 | var loadAssembliesOnStartupTypeDefinition = assemblyDefinition.MainModule.GetType("LoadAssembliesOnStartup");
28 | var loadAssembliesOnStartupMethodDefinition = loadAssembliesOnStartupTypeDefinition.Methods.First(_ => _.Name == "LoadTypesOnStartup");
29 |
30 | var methodBody = loadAssembliesOnStartupMethodDefinition.Body;
31 | methodBody.SimplifyMacros();
32 |
33 | var actualIlBuilder = new StringBuilder();
34 |
35 | foreach (var instruction in methodBody.Instructions)
36 | {
37 | var line = instruction.ToString();
38 |
39 | if (instruction.Operand is TypeReference operationTypeReference)
40 | {
41 | line += $" | {operationTypeReference.Scope}";
42 | }
43 |
44 | actualIlBuilder.AppendLine(line);
45 | }
46 |
47 | var actualIl = actualIlBuilder.ToString();
48 |
49 | var settings = new VerifySettings
50 | {
51 |
52 | };
53 |
54 | settings.UniqueForAssemblyConfiguration();
55 |
56 | // Replace versions so it never breaks on updates
57 | foreach (var assembly in new[]
58 | {
59 | typeof(Catel.CoreModule).Assembly,
60 | typeof(VerifyHelper).Assembly, // test assembly version
61 | typeof(CriticalHandleMinusOneIsInvalid).Assembly, // System.Private.CoreLib
62 | })
63 | {
64 | var search = $"Version={assembly.Version()}";
65 |
66 | settings.ScrubLinesWithReplace(replaceLine: _ =>
67 | {
68 | return _.Replace(search, "Version=Version");
69 | });
70 | }
71 |
72 | await Verifier.Verify(actualIl, settings);
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.ExcludesPrivateAssembliesAsync.Debug.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.ExcludesPrivateAssembliesAsync.Release.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.ExcludesSystemAssembliesAsync.Debug.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.ExcludesSystemAssembliesAsync.Release.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.HasNotRegisteredOrcFileSystemViaWildCardsAsync.Debug.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.HasNotRegisteredOrcFileSystemViaWildCardsAsync.Release.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ret
11 | IL_0022: ret
12 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.IncludesSystemAssembliesAsync.Debug.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ldtoken Microsoft.Win32.SafeHandles.CriticalHandleMinusOneIsInvalid | System.Private.CoreLib, Version=Version, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
11 | IL_0026: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
12 | IL_002b: stloc V_3
13 | IL_002c: ret
14 | IL_002d: ret
15 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Helpers/WeavingFacts.IncludesSystemAssembliesAsync.Release.verified.txt:
--------------------------------------------------------------------------------
1 | IL_0000: ldtoken System.ComponentModel.BeginEditEventArgs | Catel.Core, Version=Version, Culture=neutral, PublicKeyToken=null
2 | IL_0005: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
3 | IL_000a: stloc V_0
4 | IL_000b: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReference.Services.ClassThatShouldBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReference, Version=Version, Culture=neutral, PublicKeyToken=null
5 | IL_0010: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
6 | IL_0015: stloc V_1
7 | IL_0016: ldtoken LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.Services.ClassThatShouldNotBeRegistered | LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores, Version=Version, Culture=neutral, PublicKeyToken=null
8 | IL_001b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
9 | IL_0020: stloc V_2
10 | IL_0021: ldtoken System.Console | System.Console, Version=Version, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
11 | IL_0026: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
12 | IL_002b: stloc V_3
13 | IL_002c: ldtoken Microsoft.Win32.SafeHandles.CriticalHandleMinusOneIsInvalid | System.Private.CoreLib, Version=Version, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
14 | IL_0031: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
15 | IL_0036: stloc V_4
16 | IL_0038: ret
17 | IL_0039: ret
18 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/LoadAssembliesOnStartup.Fody.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | LoadAssembliesOnStartup.Fody.Tests
5 | LoadAssembliesOnStartup.Fody.Tests
6 | en-US
7 | LoadAssembliesOnStartup.Fody.Tests
8 | 1.0.0-alpha0001
9 |
10 |
11 | true
12 | true
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/MockAssemblyResolver.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using Mono.Cecil;
3 | using System.Collections.Generic;
4 |
5 | public class MockAssemblyResolver : DefaultAssemblyResolver
6 | {
7 | private readonly Dictionary _cache = new Dictionary();
8 |
9 | public override AssemblyDefinition Resolve(AssemblyNameReference name)
10 | {
11 | var fullName = name.FullName;
12 |
13 | lock (_cache)
14 | {
15 | if (!_cache.TryGetValue(fullName, out var definition))
16 | {
17 | if (name.Name == "System")
18 | {
19 | var codeBase = typeof(Debug).Assembly.Location.Replace("file:///", string.Empty);
20 | definition = AssemblyDefinition.ReadAssembly(codeBase);
21 | }
22 | else
23 | {
24 | definition = base.Resolve(name);
25 | }
26 |
27 | _cache[fullName] = definition;
28 | }
29 |
30 | return definition;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | #if DEBUG
4 | [assembly: AssemblyConfiguration("Debug")]
5 | #else
6 | [assembly: AssemblyConfiguration("Release")]
7 | #endif
8 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/WeavingFacts.PrivateAssemblies.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Tests
2 | {
3 | using System.Threading.Tasks;
4 | using NUnit.Framework;
5 |
6 | [TestFixture]
7 | public partial class WeavingFacts
8 | {
9 | [Test]
10 | public async Task ExcludesPrivateAssembliesAsync()
11 | {
12 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("ExcludesPrivateAssemblies", @"");
13 |
14 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
15 | }
16 |
17 | [Test, Explicit("Unable to resolve private assets during unit tests in .NET 5")]
18 | public async Task IncludesPrivateAssembliesAsync()
19 | {
20 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("IncludesPrivateAssemblies", @"");
21 |
22 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/WeavingFacts.SystemAssemblies.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Tests
2 | {
3 | using System.Threading.Tasks;
4 | using NUnit.Framework;
5 |
6 | [TestFixture]
7 | public partial class WeavingFacts
8 | {
9 | [Test]
10 | public async Task ExcludesSystemAssembliesAsync()
11 | {
12 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("ExcludesSystemAssemblies", @"");
13 |
14 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
15 | }
16 |
17 | [Test]
18 | public async Task IncludesSystemAssembliesAsync()
19 | {
20 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("IncludesSystemAssemblies", @"");
21 |
22 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.Tests/WeavingFacts.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Tests
2 | {
3 | using System;
4 | using System.Threading.Tasks;
5 | using Catel.Reflection;
6 | using NUnit.Framework;
7 |
8 | [TestFixture, NonParallelizable]
9 | public partial class WeavingFacts
10 | {
11 | [TestCase]
12 | public void HasRegisteredTypesInIncludedReferences()
13 | {
14 | // Load program to load assembly
15 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("IncludedReferences", @"");
16 |
17 | var programType = assemblyInfo.Assembly.GetType("LoadAssembliesOnStartup.Fody.TestAssembly.Program");
18 | var programInstance = Activator.CreateInstance(programType);
19 |
20 | var propertyInfo = programType.GetPropertyEx("IsRightAssemblyLoaded", true, true);
21 | Assert.That((bool)propertyInfo.GetValue(null, null), Is.True);
22 | }
23 |
24 | [Test, Explicit("Unable to resolve private assets during unit tests in .NET 5")]
25 | public async Task HasRegisteredOrcFileSystemViaWildCardsAsync()
26 | {
27 | // Load program to load assembly
28 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("IncludeOrcLibraries", "");
29 |
30 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
31 | }
32 |
33 | [Test]
34 | public async Task HasNotRegisteredOrcFileSystemViaWildCardsAsync()
35 | {
36 | // Load program to load assembly
37 | var assemblyInfo = AssemblyWeaver.Instance.GetAssembly("ExcludeOrcLibraries", "");
38 |
39 | await VerifyHelper.AssertIlCodeAsync(assemblyInfo.AssemblyPath);
40 | }
41 |
42 | //[TestCase]
43 | //public void HasNotRegisteredTypesInExcludedReferences()
44 | //{
45 | // AssemblyWeaver.Initialize();
46 |
47 | // var serviceLocator = ServiceLocator.Default;
48 |
49 | // Assert.IsFalse(serviceLocator.IsTypeRegistered());
50 | //}
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26403.7
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LoadAssembliesOnStartup.Fody", "LoadAssembliesOnStartup.Fody\LoadAssembliesOnStartup.Fody.csproj", "{801B49CF-35D8-4BE3-BAEF-FA024A42A66C}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{94444851-DCB1-45E1-813D-84BE58DDC23B}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadAssembliesOnStartup.Fody.Tests", "LoadAssembliesOnStartup.Fody.Tests\LoadAssembliesOnStartup.Fody.Tests.csproj", "{E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF}"
11 | EndProject
12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{1CF1A83D-E73A-405F-9970-9827C7C3335D}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadAssembliesOnStartup.Fody.TestAssembly", "LoadAssembliesOnStartup.Fody.TestAssembly\LoadAssembliesOnStartup.Fody.TestAssembly.csproj", "{2107A58E-8545-4610-A0C2-BE322E080E86}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadAssembliesOnStartup.Fody.TestAssemblyToReference", "LoadAssembliesOnStartup.Fody.TestAssemblyToReference\LoadAssembliesOnStartup.Fody.TestAssemblyToReference.csproj", "{75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores", "LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores\LoadAssembliesOnStartup.Fody.TestAssemblyToReferenceWithIgnores.csproj", "{ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06}"
19 | EndProject
20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "misc", "misc", "{EB61F600-4861-47A2-8FB6-D465E362DCB6}"
21 | ProjectSection(SolutionItems) = preProject
22 | Directory.build.project.props = Directory.build.project.props
23 | Directory.build.props = Directory.build.props
24 | Directory.build.shared.explicit.props = Directory.build.shared.explicit.props
25 | Directory.build.shared.implicit.props = Directory.build.shared.implicit.props
26 | Directory.build.targets = Directory.build.targets
27 | LoadAssembliesOnStartup.Fody.sln.DotSettings = LoadAssembliesOnStartup.Fody.sln.DotSettings
28 | nuget.config = nuget.config
29 | Settings.StyleCop = Settings.StyleCop
30 | SolutionAssemblyInfo.cs = SolutionAssemblyInfo.cs
31 | EndProjectSection
32 | EndProject
33 | Global
34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
35 | Debug|Any CPU = Debug|Any CPU
36 | Release|Any CPU = Release|Any CPU
37 | EndGlobalSection
38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
39 | {801B49CF-35D8-4BE3-BAEF-FA024A42A66C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {801B49CF-35D8-4BE3-BAEF-FA024A42A66C}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {801B49CF-35D8-4BE3-BAEF-FA024A42A66C}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {801B49CF-35D8-4BE3-BAEF-FA024A42A66C}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {2107A58E-8545-4610-A0C2-BE322E080E86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {2107A58E-8545-4610-A0C2-BE322E080E86}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {2107A58E-8545-4610-A0C2-BE322E080E86}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {2107A58E-8545-4610-A0C2-BE322E080E86}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7}.Release|Any CPU.Build.0 = Release|Any CPU
55 | {ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06}.Release|Any CPU.ActiveCfg = Release|Any CPU
58 | {ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06}.Release|Any CPU.Build.0 = Release|Any CPU
59 | EndGlobalSection
60 | GlobalSection(SolutionProperties) = preSolution
61 | HideSolutionNode = FALSE
62 | EndGlobalSection
63 | GlobalSection(NestedProjects) = preSolution
64 | {801B49CF-35D8-4BE3-BAEF-FA024A42A66C} = {94444851-DCB1-45E1-813D-84BE58DDC23B}
65 | {E23F5CF5-5C34-4D3A-8FD0-F167C12DE9CF} = {1CF1A83D-E73A-405F-9970-9827C7C3335D}
66 | {1CF1A83D-E73A-405F-9970-9827C7C3335D} = {94444851-DCB1-45E1-813D-84BE58DDC23B}
67 | {2107A58E-8545-4610-A0C2-BE322E080E86} = {1CF1A83D-E73A-405F-9970-9827C7C3335D}
68 | {75DC8CCA-B289-4EF0-BAF2-7FA95D8B2DE7} = {1CF1A83D-E73A-405F-9970-9827C7C3335D}
69 | {ACD018C2-CFBE-4AF3-92E8-53BAED5A2C06} = {1CF1A83D-E73A-405F-9970-9827C7C3335D}
70 | EndGlobalSection
71 | GlobalSection(ExtensibilityGlobals) = postSolution
72 | SolutionGuid = {D70B5D99-B2F0-4EFE-A415-34E449D96EFC}
73 | EndGlobalSection
74 | EndGlobal
75 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // --------------------------------------------------------------------------------------------------------------------
2 | //
3 | // Copyright (c) 2008 - 2014 CatenaLogic. All rights reserved.
4 | //
5 | // --------------------------------------------------------------------------------------------------------------------
6 |
7 |
8 | using System.Reflection;
9 |
10 | [assembly: AssemblyTitle("LoadAssembliesOnStartup")]
11 | [assembly: AssemblyProduct("LoadAssembliesOnStartup")]
12 | [assembly: AssemblyDescription("LoadAssembliesOnStartup plugin for Fody")]
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Configuration.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Xml.Linq;
7 |
8 | public class Configuration
9 | {
10 | public Configuration(XElement config)
11 | {
12 | OptOut = true;
13 | ExcludePrivateAssemblies = true;
14 | ExcludeSystemAssemblies = true;
15 | IncludeAssemblies = new List();
16 | ExcludeAssemblies = new List();
17 |
18 | if (config is null)
19 | {
20 | return;
21 | }
22 |
23 | if (config.Attribute(nameof(IncludeAssemblies)) is not null || config.Element(nameof(IncludeAssemblies)) is not null)
24 | {
25 | OptOut = false;
26 | }
27 |
28 | ReadList(config, nameof(ExcludeAssemblies), ExcludeAssemblies);
29 | ReadList(config, nameof(IncludeAssemblies), IncludeAssemblies);
30 | ReadBool(config, nameof(ExcludePrivateAssemblies), _ => ExcludePrivateAssemblies = _);
31 | ReadBool(config, nameof(ExcludeSystemAssemblies), _ => ExcludeSystemAssemblies = _);
32 | ReadBool(config, nameof(ExcludeOptimizedAssemblies), _ => ExcludeOptimizedAssemblies = _);
33 | ReadBool(config, nameof(WrapInTryCatch), _ => WrapInTryCatch = _);
34 |
35 | if (IncludeAssemblies.Any() && ExcludeAssemblies.Any())
36 | {
37 | throw new WeavingException("Either configure IncludeAssemblies OR ExcludeAssemblies, not both.");
38 | }
39 | }
40 |
41 | public bool OptOut { get; private set; }
42 | public List IncludeAssemblies { get; private set; }
43 | public List ExcludeAssemblies { get; private set; }
44 | public bool ExcludePrivateAssemblies { get; private set; }
45 | public bool ExcludeSystemAssemblies { get; private set; }
46 | public bool ExcludeOptimizedAssemblies { get; private set; }
47 | public bool WrapInTryCatch { get; private set; }
48 |
49 | public static void ReadList(XElement config, string nodeName, List list)
50 | {
51 | var attribute = config.Attribute(nodeName);
52 | if (attribute is not null)
53 | {
54 | foreach (var item in attribute.Value.Split('|').NonEmpty())
55 | {
56 | list.Add(item);
57 | }
58 | }
59 |
60 | var element = config.Element(nodeName);
61 | if (element is not null)
62 | {
63 | foreach (var item in element.Value.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries)
64 | .NonEmpty())
65 | {
66 | list.Add(item);
67 | }
68 | }
69 | }
70 |
71 | public static void ReadBool(XElement config, string nodeName, Action setter)
72 | {
73 | var attribute = config.Attribute(nodeName);
74 | if (attribute is not null)
75 | {
76 | if (bool.TryParse(attribute.Value, out var value))
77 | {
78 | setter(value);
79 | }
80 | else
81 | {
82 | throw new WeavingException($"Could not parse '{nodeName}' from '{attribute.Value}'.");
83 | }
84 | }
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Core/PrivateReference.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | public class PrivateReference
4 | {
5 | public PrivateReference(string packageName, string version)
6 | {
7 | PackageName = packageName;
8 | Version = version;
9 | }
10 |
11 | public string PackageName { get; }
12 |
13 | public string Version { get; }
14 |
15 | public override string ToString()
16 | {
17 | return $"{PackageName} v{Version}";
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Core/WeavingException.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 |
5 | public class WeavingException : Exception
6 | {
7 | public WeavingException(string message)
8 | : base(message)
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/AssemblyExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Reflection;
4 |
5 | internal static class AssemblyExtensions
6 | {
7 | public static string GetVersion(this Assembly assembly)
8 | {
9 | var version = GetAssemblyAttribute(assembly);
10 | return version is null ? null : version.InformationalVersion;
11 | }
12 |
13 | private static TAttibute GetAssemblyAttribute(Assembly assembly)
14 | where TAttibute : Attribute
15 | {
16 | var attibutes = assembly.GetCustomAttributes(typeof(TAttibute))?.ToArray() ?? Array.Empty();
17 | return attibutes.Length > 0 ? attibutes[0] as TAttibute : null;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/CecilExtensions.assembly.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 | using Mono.Cecil;
5 |
6 | public static partial class CecilExtensions
7 | {
8 | public static Version GetVersion(this AssemblyDefinition assemblyDefinition)
9 | {
10 | return assemblyDefinition.Name.Version;
11 |
12 | //var stringVersion = "0.0.0.0";
13 |
14 | //var assemblyVersionAttributeName = typeof(AssemblyVersionAttribute).FullName;
15 | //var assemblyFileVersionAttributeName = typeof(AssemblyFileVersionAttribute).FullName;
16 |
17 | //var attribute = assemblyDefinition.CustomAttributes.FirstOrDefault(_ => _.AttributeType.FullName == assemblyVersionAttributeName);
18 | //if (attribute is null)
19 | //{
20 | // attribute = assemblyDefinition.CustomAttributes.FirstOrDefault(_ => _.AttributeType.FullName == assemblyFileVersionAttributeName);
21 | //}
22 |
23 | //if (attribute != null)
24 | //{
25 | // stringVersion = (string)attribute.ConstructorArguments.First().Value;
26 | //}
27 |
28 | //var version = new Version(stringVersion);
29 | //return version;
30 | }
31 |
32 | public static bool IsNetCoreLibrary(this AssemblyDefinition assemblyDefinition)
33 | {
34 | if (IsNetStandardLibrary(assemblyDefinition))
35 | {
36 | return false;
37 | }
38 |
39 | var mainModule = assemblyDefinition.MainModule;
40 | if (mainModule.Types.Count == 1)
41 | {
42 | return true;
43 | }
44 |
45 | return false;
46 | }
47 |
48 | public static bool IsNetStandardLibrary(this AssemblyDefinition assemblyDefinition)
49 | {
50 | return assemblyDefinition.MainModule.FileName.IndexOf("netstandard", 0, StringComparison.OrdinalIgnoreCase) >= 0;
51 | }
52 |
53 | public static AssemblyDefinition Resolve(this IAssemblyResolver assemblyResolver, string name)
54 | {
55 | return assemblyResolver.Resolve(new AssemblyNameReference(name, null));
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/CecilExtensions.attributes.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using Mono.Cecil;
6 | using Mono.Collections.Generic;
7 |
8 | public static partial class CecilExtensions
9 | {
10 | public static CustomAttribute GetAttribute(this TypeDefinition typeDefinition, string attributeName)
11 | {
12 | return GetAttribute(typeDefinition.CustomAttributes, attributeName);
13 | }
14 |
15 | public static CustomAttribute GetAttribute(this PropertyDefinition propertyDefinition, string attributeName)
16 | {
17 | return GetAttribute(propertyDefinition.CustomAttributes, attributeName);
18 | }
19 |
20 | public static CustomAttribute GetAttribute(Collection customAttributes, string attributeName)
21 | {
22 | return GetAttributes(customAttributes, attributeName).FirstOrDefault();
23 | }
24 |
25 | public static IEnumerable GetAttributes(this TypeDefinition typeDefinition, string attributeName)
26 | {
27 | return GetAttributes(typeDefinition.CustomAttributes, attributeName);
28 | }
29 |
30 | public static IEnumerable GetAttributes(this PropertyDefinition propertyDefinition, string attributeName)
31 | {
32 | return GetAttributes(propertyDefinition.CustomAttributes, attributeName);
33 | }
34 |
35 | public static IEnumerable GetAttributes(Collection customAttributes, string attributeName)
36 | {
37 | return (from attribute in customAttributes
38 | where attribute.Constructor.DeclaringType.FullName.Contains(attributeName)
39 | select attribute);
40 | }
41 |
42 | public static bool IsDecoratedWithAttribute(this TypeDefinition typeDefinition, string attributeName)
43 | {
44 | return IsDecoratedWithAttribute(typeDefinition.CustomAttributes, attributeName);
45 | }
46 |
47 | public static bool IsDecoratedWithAttribute(this ParameterDefinition parameterDefinition, string attributeName)
48 | {
49 | return IsDecoratedWithAttribute(parameterDefinition.CustomAttributes, attributeName);
50 | }
51 |
52 | public static bool IsDecoratedWithAttribute(this PropertyDefinition propertyDefinition, string attributeName)
53 | {
54 | return IsDecoratedWithAttribute(propertyDefinition.CustomAttributes, attributeName);
55 | }
56 |
57 | public static bool IsDecoratedWithAttribute(Collection customAttributes, string attributeName)
58 | {
59 | return GetAttribute(customAttributes, attributeName) is not null;
60 | }
61 |
62 | public static void RemoveAttribute(this TypeDefinition typeDefinition, string attributeName)
63 | {
64 | RemoveAttribute(typeDefinition.CustomAttributes, attributeName);
65 | }
66 |
67 | public static void RemoveAttribute(this ParameterDefinition typeDefinition, string attributeName)
68 | {
69 | RemoveAttribute(typeDefinition.CustomAttributes, attributeName);
70 | }
71 |
72 | public static void RemoveAttribute(this PropertyDefinition propertyDefinition, string attributeName)
73 | {
74 | RemoveAttribute(propertyDefinition.CustomAttributes, attributeName);
75 | }
76 |
77 | public static void RemoveAttribute(Collection customAttributes, string attributeName)
78 | {
79 | var attributes = (from attribute in customAttributes
80 | where attribute.Constructor.DeclaringType.FullName.Contains(attributeName)
81 | select attribute).ToList();
82 |
83 | foreach (var attribute in attributes)
84 | {
85 | customAttributes.Remove(attribute);
86 | }
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/CecilExtensions.debuginfo.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Linq;
4 | using System.Reflection;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 | using Mono.Collections.Generic;
8 |
9 | public static partial class CecilExtensions
10 | {
11 | private const long AddressToIgnore = 16707566;
12 |
13 | private static readonly FieldInfo SequencePointOffsetFieldInfo = typeof(SequencePoint).GetField("offset", BindingFlags.Instance | BindingFlags.NonPublic);
14 | private static readonly FieldInfo InstructionOffsetInstructionFieldInfo = typeof(InstructionOffset).GetField("instruction", BindingFlags.Instance | BindingFlags.NonPublic);
15 |
16 | public static void UpdateDebugInfo(this MethodDefinition method)
17 | {
18 | var debugInfo = method.DebugInformation;
19 | var instructions = method.Body.Instructions;
20 | var scope = debugInfo.Scope;
21 |
22 | if (scope is null || instructions.Count == 0)
23 | {
24 | return;
25 | }
26 |
27 | var oldSequencePoints = debugInfo.SequencePoints;
28 | var newSequencePoints = new Collection();
29 |
30 | // Step 1: check if all variables are present
31 | foreach (var variable in method.Body.Variables)
32 | {
33 | var hasVariable = scope.Variables.Any(_ => _.Index == variable.Index);
34 | if (!hasVariable)
35 | {
36 | var variableDebugInfo = new VariableDebugInformation(variable, $"__var_{variable.Index}");
37 | scope.Variables.Add(variableDebugInfo);
38 | }
39 | }
40 |
41 | // Step 2: Make sure the instructions point to the correct items
42 | foreach (var oldSequencePoint in oldSequencePoints)
43 | {
44 | //var isValid = false;
45 |
46 | //// Special cases we need to ignore
47 | //if (oldSequencePoint.StartLine == AddressToIgnore ||
48 | // oldSequencePoint.EndLine == AddressToIgnore)
49 | //{
50 | // continue;
51 | //}
52 |
53 | var instructionOffset = (InstructionOffset)SequencePointOffsetFieldInfo.GetValue(oldSequencePoint);
54 | var offsetInstruction = (Instruction)InstructionOffsetInstructionFieldInfo.GetValue(instructionOffset);
55 |
56 | // Fix offset
57 | for (var i = 0; i < instructions.Count; i++)
58 | {
59 | var instruction = instructions[i];
60 | if (instruction == offsetInstruction)
61 | {
62 | var newSequencePoint = new SequencePoint(instruction, oldSequencePoint.Document)
63 | {
64 | StartLine = oldSequencePoint.StartLine,
65 | StartColumn = oldSequencePoint.StartColumn,
66 | EndLine = oldSequencePoint.EndLine,
67 | EndColumn = oldSequencePoint.EndColumn
68 | };
69 |
70 | newSequencePoints.Add(newSequencePoint);
71 |
72 | //isValid = true;
73 |
74 | break;
75 | }
76 | }
77 | }
78 |
79 | debugInfo.SequencePoints.Clear();
80 |
81 | foreach (var newSequencePoint in newSequencePoints)
82 | {
83 | debugInfo.SequencePoints.Add(newSequencePoint);
84 | }
85 |
86 | // Step 3: update the scopes by setting the indices
87 | scope.Start = new InstructionOffset(instructions.First());
88 | scope.End = new InstructionOffset(instructions.Last());
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/CecilExtensions.fields.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using Mono.Cecil;
4 |
5 | public static partial class CecilExtensions
6 | {
7 | public static FieldReference MakeGeneric(this FieldReference field, TypeReference declaringType)
8 | {
9 | var reference = new FieldReference(field.Name, field.FieldType)
10 | {
11 | DeclaringType = declaringType.MakeGenericIfRequired(),
12 | };
13 |
14 | return reference;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/CecilExtensions.methods.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 |
8 | public static partial class CecilExtensions
9 | {
10 | public static int FindBaseConstructorIndex(this MethodDefinition method)
11 | {
12 | var declaringType = method.DeclaringType;
13 | if (declaringType is not null)
14 | {
15 | var baseType = declaringType.BaseType;
16 | if (baseType is not null)
17 | {
18 | var instructions = method.Body.Instructions;
19 |
20 | for (var i = 0; i < instructions.Count; i++)
21 | {
22 | var instruction = instructions[i];
23 | if (instruction.IsOpCode(OpCodes.Call))
24 | {
25 | var methodReference = instruction.Operand as MethodReference;
26 | if (methodReference is not null)
27 | {
28 | if (methodReference.Name.Equals(".ctor"))
29 | {
30 | var ctorDeclaringType = methodReference.DeclaringType?.FullName;
31 | if (baseType.FullName.Equals(ctorDeclaringType))
32 | {
33 | return i;
34 | }
35 | }
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
42 | return -1;
43 | }
44 |
45 | public static SequencePoint GetFirstSequencePoint(this MethodDefinition method)
46 | {
47 | return method.DebugInformation.SequencePoints.FirstOrDefault();
48 | }
49 |
50 | public static SequencePoint GetSequencePoint(this MethodDefinition method, Instruction instruction)
51 | {
52 | var debugInfo = method.DebugInformation;
53 | return debugInfo.GetSequencePoint(instruction);
54 | }
55 |
56 | public static MethodReference MakeGeneric(this MethodReference method, TypeReference declaringType)
57 | {
58 | var reference = new MethodReference(method.Name, method.ReturnType)
59 | {
60 | DeclaringType = declaringType.MakeGenericIfRequired(),
61 | HasThis = method.HasThis,
62 | ExplicitThis = method.ExplicitThis,
63 | CallingConvention = method.CallingConvention,
64 | };
65 |
66 | foreach (var parameter in method.Parameters)
67 | {
68 | reference.Parameters.Add(new ParameterDefinition(parameter.ParameterType));
69 | }
70 |
71 | return reference;
72 | }
73 |
74 | public static MethodReference GetMethodReference(this MethodDefinition methodDefinition, Stack typeDefinitions)
75 | {
76 | var methodReference = FodyEnvironment.ModuleDefinition.ImportReference(methodDefinition).GetGeneric();
77 |
78 | if (methodDefinition.IsStatic)
79 | {
80 | return methodReference;
81 | }
82 |
83 | typeDefinitions.Pop();
84 | while (typeDefinitions.Count > 0)
85 | {
86 | var definition = typeDefinitions.Pop();
87 |
88 | // Only call lower class if possible
89 | var containsMethod = (from method in definition.Methods
90 | where method.Name == methodDefinition.Name
91 | select method).Any();
92 | if (containsMethod)
93 | {
94 | methodReference = methodReference.MakeGeneric(definition.BaseType);
95 | }
96 | }
97 |
98 | return methodReference;
99 | }
100 | }
101 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/InstructionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using Mono.Cecil;
4 | using Mono.Cecil.Cil;
5 |
6 | public static class InstructionExtensions
7 | {
8 | public static bool IsOpCode(this Instruction instruction, params OpCode[] opCodes)
9 | {
10 | if (opCodes.Length == 0)
11 | {
12 | return true;
13 | }
14 |
15 | foreach (var opCode in opCodes)
16 | {
17 | if (instruction.OpCode == opCode)
18 | {
19 | return true;
20 | }
21 | }
22 |
23 | return false;
24 | }
25 |
26 | public static bool UsesType(this Instruction instruction, TypeDefinition typeDefinition, params OpCode[] opCodes)
27 | {
28 | if (instruction.IsOpCode(opCodes))
29 | {
30 | var fieldDefinition = instruction.Operand as FieldDefinition;
31 | if (fieldDefinition is not null)
32 | {
33 | if (string.Equals(fieldDefinition.DeclaringType.Name, typeDefinition.Name))
34 | {
35 | return true;
36 | }
37 | }
38 |
39 | var fieldReference = instruction.Operand as FieldReference;
40 | if (fieldReference is not null)
41 | {
42 | if (string.Equals(fieldReference.DeclaringType.Name, typeDefinition.Name))
43 | {
44 | return true;
45 | }
46 | }
47 |
48 | var methodDefinition = instruction.Operand as MethodDefinition;
49 | if (methodDefinition is not null)
50 | {
51 | if (string.Equals(methodDefinition.DeclaringType.Name, typeDefinition.Name))
52 | {
53 | return true;
54 | }
55 | }
56 |
57 | var methodReference = instruction.Operand as MethodReference;
58 | if (methodReference is not null)
59 | {
60 | if (string.Equals(methodReference.DeclaringType.Name, typeDefinition.Name))
61 | {
62 | return true;
63 | }
64 | }
65 | }
66 |
67 | return false;
68 | }
69 |
70 | public static bool UsesField(this Instruction instruction, FieldDefinition fieldDefinition)
71 | {
72 | var usedFieldDefinition = instruction.Operand as FieldDefinition;
73 | if (usedFieldDefinition is not null)
74 | {
75 | if (string.Equals(usedFieldDefinition.Name, fieldDefinition.Name))
76 | {
77 | return true;
78 | }
79 | }
80 |
81 | var usedFieldReference = instruction.Operand as FieldReference;
82 | if (usedFieldReference is not null)
83 | {
84 | if (string.Equals(usedFieldReference.Name, fieldDefinition.Name))
85 | {
86 | return true;
87 | }
88 | }
89 |
90 | return false;
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/InstructionListExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 | using Mono.Collections.Generic;
8 |
9 | public static class InstructionListExtensions
10 | {
11 | public static bool IsNextInstructionOpCode(this IList instructions, int index, params OpCode[] opCodes)
12 | {
13 | var instruction = (instructions.Count > index + 1) ? instructions[index + 1] : null;
14 | if (instruction is null)
15 | {
16 | return false;
17 | }
18 |
19 | return instruction.IsOpCode(opCodes);
20 | }
21 |
22 | public static void MoveInstructionsToPosition(this IList instructions, int startIndex, int length, int targetPosition)
23 | {
24 | var instructionsToMove = new List();
25 | for (var i = startIndex; i < startIndex + length; i++)
26 | {
27 | instructionsToMove.Add(instructions[startIndex]);
28 | instructions.RemoveAt(startIndex);
29 | }
30 |
31 | if (startIndex < targetPosition)
32 | {
33 | targetPosition -= instructionsToMove.Count;
34 | }
35 |
36 | Insert(instructions, targetPosition, instructionsToMove);
37 | }
38 |
39 | public static void MoveInstructionsToEnd(this IList instructions, int startIndex, int length)
40 | {
41 | MoveInstructionsToPosition(instructions, startIndex, length, instructions.Count - 1);
42 | }
43 |
44 | public static Instruction GetPreviousInstruction(this IList instructions, Instruction instruction)
45 | {
46 | var currentIndex = instructions.IndexOf(instruction);
47 | if (currentIndex <= 0)
48 | {
49 | return null;
50 | }
51 |
52 | return instructions[currentIndex - 1];
53 | }
54 |
55 | public static bool UsesType(this IList instructions, TypeDefinition typeDefinition, params OpCode[] opCodes)
56 | {
57 | for (var index = 0; index < instructions.Count; index++)
58 | {
59 | var instruction = instructions[index];
60 | if (instruction.UsesType(typeDefinition, opCodes))
61 | {
62 | return true;
63 | }
64 | }
65 |
66 | return false;
67 | }
68 |
69 | public static bool UsesField(this IList instructions, FieldDefinition field)
70 | {
71 | for (var index = 0; index < instructions.Count; index++)
72 | {
73 | var instruction = instructions[index];
74 | if (instruction.UsesField(field))
75 | {
76 | return true;
77 | }
78 | }
79 |
80 | return false;
81 | }
82 |
83 | public static void Prepend(this Collection collection, params Instruction[] instructions)
84 | {
85 | for (var index = 0; index < instructions.Length; index++)
86 | {
87 | var instruction = instructions[index];
88 | collection.Insert(index, instruction);
89 | }
90 | }
91 |
92 | public static void Append(this Collection collection, params Instruction[] instructions)
93 | {
94 | for (var index = 0; index < instructions.Length; index++)
95 | {
96 | collection.Insert(index, instructions[index]);
97 | }
98 | }
99 |
100 | public static void BeforeLast(this Collection collection, params Instruction[] instructions)
101 | {
102 | var index = collection.Count - 1;
103 | foreach (var instruction in instructions)
104 | {
105 | collection.Insert(index, instruction);
106 | index++;
107 | }
108 | }
109 |
110 | public static int Insert(this IList collection, int index, List instructions)
111 | {
112 | return Insert(collection, index, instructions.ToArray());
113 | }
114 |
115 | public static int Insert(this IList collection, int index, params Instruction[] instructions)
116 | {
117 | foreach (var instruction in instructions.Reverse())
118 | {
119 | collection.Insert(index, instruction);
120 | }
121 | return index + instructions.Length;
122 | }
123 | }
124 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/ResolvingExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | using Mono.Cecil;
7 |
8 | public static class ResolvingExtensions
9 | {
10 | private static readonly Dictionary _definitions = CacheHelper.GetCache>("ResolvingExtensions");
11 |
12 | public static TypeDefinition ResolveType(this TypeReference reference)
13 | {
14 | TypeDefinition definition;
15 | if (_definitions.TryGetValue(reference.FullName, out definition))
16 | {
17 | return definition;
18 | }
19 |
20 | return _definitions[reference.FullName] = InnerResolveType(reference);
21 | }
22 |
23 | private static TypeDefinition InnerResolveType(this TypeReference reference)
24 | {
25 | try
26 | {
27 | return reference.Resolve();
28 | }
29 | catch (Exception exception)
30 | {
31 | throw new Exception($"Could not resolve '{reference.FullName}'.", exception);
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/StringExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Collections.Generic;
4 | using System.Linq;
5 |
6 | public static class StringExtensions
7 | {
8 | public static IEnumerable NonEmpty(this IEnumerable list)
9 | {
10 | return list.Select(_ => _.Trim()).Where(_ => _ != string.Empty);
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Extensions/TypeReferenceExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Linq;
4 | using Mono.Cecil;
5 |
6 | public static class TypeReferenceExtensions
7 | {
8 | #region Methods
9 | public static bool IsAssignableFrom(this TypeReference target, TypeReference type)
10 | {
11 | target = type.Module.ImportReference(target).Resolve();
12 |
13 | var typeDefinition = type.Resolve();
14 |
15 | while (typeDefinition is not null)
16 | {
17 | if (typeDefinition.Equals(target))
18 | {
19 | return true;
20 | }
21 |
22 | if (typeDefinition.Interfaces.Any(_ => _.InterfaceType.Equals(target)))
23 | {
24 | return true;
25 | }
26 |
27 | typeDefinition = typeDefinition.BaseType?.Resolve();
28 | }
29 |
30 | return false;
31 | }
32 | #endregion
33 | }
34 | }
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/FodyEnvironment.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 | using System.Xml.Linq;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 |
8 | public static class FodyEnvironment
9 | {
10 | public static ModuleDefinition ModuleDefinition { get; set; }
11 | public static IAssemblyResolver AssemblyResolver { get; set; }
12 |
13 | public static XElement Config { get; set; }
14 |
15 | public static Action WriteDebug { get; set; }
16 |
17 | public static Action WriteInfo { get; set; }
18 |
19 | public static Action WriteWarning { get; set; }
20 |
21 | public static Action WriteWarningPoint { get; set; }
22 |
23 | public static Action WriteError { get; set; }
24 |
25 | public static Action WriteErrorPoint { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Helpers/CacheHelper.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System.Collections;
4 | using System.Collections.Generic;
5 |
6 | public static class CacheHelper
7 | {
8 | private static readonly Dictionary _cacheByName = new Dictionary();
9 |
10 | public static T GetCache(string name)
11 | where T : IDictionary, new()
12 | {
13 | if (!_cacheByName.ContainsKey(name))
14 | {
15 | _cacheByName[name] = new T();
16 | }
17 |
18 | return (T)_cacheByName[name];
19 | }
20 |
21 | public static void ClearAllCaches()
22 | {
23 | foreach (var cache in _cacheByName)
24 | {
25 | cache.Value.Clear();
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/LoadAssembliesOnStartup.Fody.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | LoadAssembliesOnStartup.Fody
5 | LoadAssembliesOnStartup.Fody
6 | en-US
7 | LoadAssembliesOnStartup.Fody
8 | 3.0.0-alpha0001
9 | Fody add-in for forcing referenced assemblies to be loaded on startup. This allows other modules to register types without actually having to using their types directly.
10 | true
11 | load;assemblies;references;reference;force;startup;fody;ilweaving;weaving
12 | true
13 | $(NoWarn);NU5100;NU5118;NU5128
14 |
15 |
16 |
17 |
18 | 11688DF4-BB8B-4BC8-B2F4-78DF23292EF6
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 |
40 |
41 |
42 | $(TargetsForTfmSpecificContentInPackage);IncludeFodyFiles
43 | true
44 | $(OverridableOutputPath)\..\$(PackageId)
45 | Debug;Release;Test
46 |
47 |
48 |
49 |
50 | false
51 |
52 |
53 |
54 |
55 | $(WeaverDirPath)\netstandard2.0\$(PackageId).dll
56 | $(WeaverDirPath)\netstandard2.0\$(PackageId).xcf
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/LoadAssembliesOnStartup.Fody.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/LoadAssembliesOnStartup.Fody.xcf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | A list of assembly names to exclude from loading at startup, delimited with line breaks. This will process all assemblies except these assemblies.
8 |
9 |
10 |
11 |
12 |
13 | A list of assembly names to include from loading at startup, delimited with line breaks. This will process only these these assemblies.
14 |
15 |
16 |
17 |
18 |
19 |
20 | A list of assembly names to exclude from loading at startup, delimited with line breaks. This will process all assemblies except these assemblies.
21 |
22 |
23 |
24 |
25 |
26 | A list of assembly names to include from loading at startup, delimited with line breaks. This will process only these these assemblies.
27 |
28 |
29 |
30 |
31 |
32 | Exclude assemblies that are optimized away by the compiler. The default value is false, so optimized assemblies will still be included.
33 |
34 |
35 |
36 |
37 |
38 |
39 | Exclude private assemblies in modern SDK projects (e.g. PackageReference PrivateAssets='all' />). The default value is true.
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Exclude system assemblies (e.g. System.Runtime.Serialization). The default value is true.
48 |
49 |
50 |
51 |
52 |
53 |
54 | Wrap the assembly loading in a try - catch. The default value is false.
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/ModuleWeaver.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody
2 | {
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using global::Fody;
8 | using Weaving;
9 | using Mono.Cecil;
10 |
11 | public class ModuleWeaver : BaseModuleWeaver
12 | {
13 | public override bool ShouldCleanReference => true;
14 |
15 | public override IEnumerable GetAssembliesForScanning()
16 | {
17 | var assemblies = new List();
18 |
19 | // For now just return all references
20 | assemblies.Add("netstandard");
21 | assemblies.AddRange(ModuleDefinition.AssemblyReferences.Select(_ => _.Name));
22 |
23 | return assemblies;
24 | }
25 |
26 | public override void Execute()
27 | {
28 | try
29 | {
30 | #if DEBUG
31 | if (!Debugger.IsAttached)
32 | {
33 | //Debugger.Launch();
34 | }
35 | #endif
36 |
37 | // First of all, set the assembly resolver
38 | if (AssemblyResolver is null)
39 | {
40 | AssemblyResolver = ModuleDefinition.AssemblyResolver;
41 | }
42 |
43 | // Clear cache because static members will be re-used over multiple builds over multiple systems
44 | CacheHelper.ClearAllCaches();
45 |
46 | InitializeEnvironment();
47 |
48 | // Read config
49 | var configuration = new Configuration(Config);
50 |
51 | WriteInfo($"LoadAssembliesOnStartup.Fody v{GetType().Assembly.GetVersion()}");
52 |
53 | // Set up the basics
54 | var msCoreReferenceFinder = new MsCoreReferenceFinder(this, ModuleDefinition.AssemblyResolver);
55 | msCoreReferenceFinder.Execute();
56 |
57 | // Create method that imports the types
58 | var loadTypesWeaver = new LoadTypesWeaver(ModuleDefinition, msCoreReferenceFinder, configuration, this);
59 | var loadTypesMethod = loadTypesWeaver.Execute();
60 |
61 | // Call method on assembly init
62 | var moduleLoaderImporter = new ModuleLoaderImporter();
63 | moduleLoaderImporter.ImportModuleLoader(ModuleDefinition, loadTypesMethod, msCoreReferenceFinder);
64 | }
65 | catch (Exception ex)
66 | {
67 | WriteError(ex.Message);
68 |
69 | #if DEBUG
70 | Debugger.Launch();
71 | #endif
72 | }
73 | }
74 |
75 | private void InitializeEnvironment()
76 | {
77 | FodyEnvironment.ModuleDefinition = ModuleDefinition;
78 | FodyEnvironment.AssemblyResolver = AssemblyResolver;
79 |
80 | FodyEnvironment.Config = Config;
81 | FodyEnvironment.WriteDebug = WriteDebug;
82 | FodyEnvironment.WriteInfo = WriteInfo;
83 | FodyEnvironment.WriteWarning = WriteWarning;
84 | FodyEnvironment.WriteWarningPoint = WriteWarning;
85 | FodyEnvironment.WriteError = WriteError;
86 | FodyEnvironment.WriteErrorPoint = WriteError;
87 |
88 | if (string.IsNullOrEmpty(References))
89 | {
90 | References = string.Empty;
91 | }
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/LoadAssembliesOnStartup.Fody/Weaving/ModuleLoaderImporter.cs:
--------------------------------------------------------------------------------
1 | namespace LoadAssembliesOnStartup.Fody.Weaving
2 | {
3 | using System;
4 | using System.Linq;
5 | using Mono.Cecil;
6 | using Mono.Cecil.Cil;
7 |
8 | public class ModuleLoaderImporter
9 | {
10 | public void ImportModuleLoader(ModuleDefinition moduleDefinition, MethodReference methodToCall,
11 | MsCoreReferenceFinder msCoreReferenceFinder)
12 | {
13 | const MethodAttributes attributes = MethodAttributes.Private
14 | | MethodAttributes.HideBySig
15 | | MethodAttributes.Static
16 | | MethodAttributes.SpecialName
17 | | MethodAttributes.RTSpecialName;
18 |
19 | var moduleClass = moduleDefinition.Types.FirstOrDefault(_ => _.Name == "");
20 | if (moduleClass is null)
21 | {
22 | throw new WeavingException("Found no module class!");
23 | }
24 |
25 | var cctor = moduleClass.Methods.FirstOrDefault(_ => _.Name == ".cctor");
26 | if (cctor is null)
27 | {
28 | cctor = new MethodDefinition(".cctor", attributes, moduleDefinition.ImportReference(msCoreReferenceFinder.GetCoreTypeReference("Void")));
29 | cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
30 | moduleClass.Methods.Add(cctor);
31 | }
32 |
33 | var importedMethodToCall = moduleDefinition.ImportReference(methodToCall);
34 |
35 | var insertLocation = Math.Max(cctor.Body.Instructions.Count - 2, 0);
36 | cctor.Body.Instructions.Insert(insertLocation, Instruction.Create(OpCodes.Call, importedMethodToCall));
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/MethodTimeLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | //using Catel.Logging;
3 | using System;
4 | using System.Globalization;
5 |
6 | ///
7 | /// Note: do not rename this class or put it inside a namespace.
8 | ///
9 | internal static class MethodTimeLogger
10 | {
11 | public static void Log(MethodBase methodBase, long milliseconds, string message)
12 | {
13 | Log(methodBase.DeclaringType ?? typeof(object), methodBase.Name, milliseconds, message);
14 | }
15 |
16 | public static void Log(Type type, string methodName, long milliseconds, string message)
17 | {
18 | // if (type is null)
19 | // {
20 | // return;
21 | // }
22 |
23 | // if (milliseconds == 0)
24 | // {
25 | // // Don't log superfast methods
26 | // return;
27 | // }
28 |
29 | // var finalMessage = $"[METHODTIMER] {type.Name}.{methodName} took '{milliseconds.ToString(CultureInfo.InvariantCulture)}' ms";
30 |
31 | // if (!string.IsNullOrWhiteSpace(message))
32 | // {
33 | // finalMessage += $" | {message}";
34 | // }
35 |
36 | // var logger = LogManager.GetLogger(type);
37 | // logger.Debug(finalMessage);
38 | }
39 | }
--------------------------------------------------------------------------------
/src/SolutionAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by Cake.
4 | //
5 | //------------------------------------------------------------------------------
6 | using System.Reflection;
7 |
8 | [assembly: AssemblyCompany("Fody")]
9 | [assembly: AssemblyVersion("4.7.0")]
10 | [assembly: AssemblyFileVersion("4.7.0")]
11 | [assembly: AssemblyInformationalVersion("4.7.0-beta.0")]
12 | [assembly: AssemblyCopyright("Copyright © Fody 2015 - 2025")]
13 |
14 |
--------------------------------------------------------------------------------
/src/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "msbuild-sdks": {
3 | "MSBuild.Sdk.Extras": "3.0.44"
4 | },
5 | "sdk": {
6 | "version": "9.0.0",
7 | "rollForward": "latestMinor",
8 | "allowPrerelease": false
9 | }
10 | }
--------------------------------------------------------------------------------
/src/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tools/nuget.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Fody/LoadAssembliesOnStartup/c81115bbb91f4ca9f8759628f38813e4752958eb/tools/nuget.exe
--------------------------------------------------------------------------------