├── .gitattributes
├── .github
    └── workflows
    │   ├── PublishNuget.yml
    │   └── dotnetcore.yml
├── .gitignore
├── Directory.Build.props
├── LICENSE
├── README.md
├── README.zh-cn.md
├── build
    └── Version.props
├── docs
    ├── en-us
    │   └── README.md
    └── zh-cn
    │   ├── 2018-09-29-20-36-48.png
    │   ├── AttachFile.md
    │   ├── Behavior.md
    │   ├── DefaultIgnoreFile.md
    │   ├── IncludeSourceYardPackageReference.md
    │   ├── README.md
    │   ├── SourceYardExcludeFileItem.md
    │   ├── SourceYardExcludePackageReference.md
    │   ├── about.md
    │   └── get-started.md
├── dotnetCampus.SourceYard.sln
├── dotnetCampus.SourceYard.sln.DotSettings
├── sample
    ├── App
    │   ├── AppUsingDll
    │   │   ├── AppUsingDll.csproj
    │   │   └── Program.cs
    │   ├── AppUsingSource
    │   │   ├── AppUsingSource.csproj
    │   │   ├── Program.cs
    │   │   └── SourceProject
    │   │   │   └── .gitignore
    │   └── TheLib
    │   │   ├── Money.cs
    │   │   ├── Resource
    │   │       ├── F1.md
    │   │       └── F2.md
    │   │   ├── TheLib.csproj
    │   │   ├── foo.coin
    │   │   └── foo1.coin
    ├── Directory.Build.props
    ├── README.md
    ├── Sample.sln
    ├── WPF
    │   ├── WpfApp
    │   │   ├── App.xaml
    │   │   ├── App.xaml.cs
    │   │   ├── MainWindow.xaml
    │   │   ├── MainWindow.xaml.cs
    │   │   ├── Properties
    │   │   │   ├── AssemblyInfo.cs
    │   │   │   ├── Resources.Designer.cs
    │   │   │   ├── Resources.resx
    │   │   │   ├── Settings.Designer.cs
    │   │   │   └── Settings.settings
    │   │   ├── SourceProject
    │   │   │   └── .gitignore
    │   │   └── WpfApp.csproj
    │   └── WpfUI
    │   │   ├── InterestingControl.xaml
    │   │   ├── InterestingControl.xaml.cs
    │   │   └── WpfUI.csproj
    └── build
    │   └── Version.props
├── src
    └── dotnetCampus.SourceYard
    │   ├── Assets
    │       ├── Current
    │       │   ├── Core.targets
    │       │   ├── build
    │       │   │   ├── PackageId.props
    │       │   │   └── PackageId.targets
    │       │   └── buildMultiTargeting
    │       │   │   ├── PackageId.props
    │       │   │   └── PackageId.targets
    │       ├── README.md
    │       ├── README.zh-cn.md
    │       └── Target
    │       │   └── build
    │       │       ├── $(PackageId).SourceProject.props
    │       │       ├── $(PackageId).props
    │       │       └── $(PackageId).targets
    │   ├── Cli
    │       └── Options.cs
    │   ├── Context
    │       ├── IPackingContext.cs
    │       ├── MultiTargetingPackageInfo.cs
    │       ├── PackagedProjectFile.cs
    │       ├── PackingContext.cs
    │       ├── SourceYardPackageFile.cs
    │       └── TargetFrameworkPackageInfo.cs
    │   ├── Exception_
    │       └── PackingException.cs
    │   ├── Logger_
    │       ├── ILogger.cs
    │       └── Logger.cs
    │   ├── PackFlow
    │       ├── AssetsPacker.cs
    │       ├── IPackFlow.cs
    │       ├── ItemGroupPacker.cs
    │       ├── NuGetPacker.cs
    │       ├── NuspecFileGenerator.cs
    │       ├── NuspecFiles
    │       │   ├── DependenciesParser.cs
    │       │   └── NuspecContexts
    │       │   │   ├── NuspecDependency.cs
    │       │   │   ├── NuspecFrameworkAssembly.cs
    │       │   │   ├── NuspecGroup.cs
    │       │   │   ├── NuspecMetadata.cs
    │       │   │   └── NuspecPackage.cs
    │       ├── Package.cs
    │       └── SourcePacker.cs
    │   ├── Packer.cs
    │   ├── Program.cs
    │   ├── Utils
    │       ├── BuildProps.cs
    │       ├── CombineReadonlyList.cs
    │       ├── FileSystem.cs
    │       ├── ItemGroupElement.cs
    │       ├── ReferenceVersion.cs
    │       ├── SemanticVersion.cs
    │       └── VersionField.cs
    │   ├── dotnetCampus.SourceYard.csproj
    │   └── dotnetCampus.SourceYard.csproj.DotSettings
└── tests
    ├── SourceYardLaunchSettingsDemo
        ├── Program.cs
        ├── Properties
        │   └── launchSettings.json
        └── SourceYardLaunchSettingsDemo.csproj
    ├── SourceYardTestDemo
        ├── Program.cs
        ├── SourceYardTestDemo.csproj
        └── SourceYardTestDemo.sln
    └── dotnetCampus.SourceYard.Tests
        └── dotnetCampus.SourceYard.Tests.csproj
/.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/workflows/PublishNuget.yml:
--------------------------------------------------------------------------------
 1 | name: publish nuget
 2 | 
 3 | on: 
 4 |   push:
 5 |     tags:
 6 |     - '*'
 7 | 
 8 | jobs:
 9 |   build:
10 | 
11 |     runs-on: windows-latest
12 | 
13 |     steps:
14 |     - uses: actions/checkout@v1
15 |  
16 |     - name: Setup .NET Core
17 |       uses: actions/setup-dotnet@v1
18 |       with:
19 |         dotnet-version: 3.1.202
20 | 
21 |     - name: Install tool
22 |       run: dotnet tool install -g dotnetCampus.TagToVersion
23 | 
24 |     - name: Set tag to version
25 |       run: dotnet TagToVersion -t ${{ github.ref }}  
26 | 
27 |     - name: Build with dotnet
28 |       run: dotnet build --configuration Release
29 |     - name: Install Nuget
30 |       run: |
31 |         $sourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
32 |         $targetNugetExe = "nuget.exe"
33 |         Invoke-WebRequest $sourceNugetExe -OutFile $targetNugetExe
34 |     - name: Add private GitHub registry to NuGet
35 |       run: |
36 |         .\nuget sources add -name github -Source https://nuget.pkg.github.com/ORGANIZATION_NAME/index.json -Username ORGANIZATION_NAME -Password ${{ secrets.GITHUB_TOKEN }}
37 |     - name: Push generated package to GitHub registry
38 |       run: |
39 |         .\nuget push .\bin\release\*.nupkg -Source github -SkipDuplicate
40 |         .\nuget push .\bin\release\*.nupkg -Source https://api.nuget.org/v3/index.json -SkipDuplicate -ApiKey ${{ secrets.NugetKey }} -NoSymbols 
41 | 
--------------------------------------------------------------------------------
/.github/workflows/dotnetcore.yml:
--------------------------------------------------------------------------------
 1 | name: .NET Core
 2 | 
 3 | on: [push]
 4 | 
 5 | jobs:
 6 |   build:
 7 | 
 8 |     runs-on: windows-latest
 9 | 
10 |     steps:
11 |     - uses: actions/checkout@v1
12 |     - name: Setup .NET Core
13 |       uses: actions/setup-dotnet@v1
14 |       with:
15 |         dotnet-version: 3.1.201
16 |     - name: Build with dotnet
17 |       run: dotnet build --configuration Release
18 | 
--------------------------------------------------------------------------------
/.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 | *.userosscache
  8 | *.sln.docstates
  9 | 
 10 | # User-specific files (MonoDevelop/Xamarin Studio)
 11 | *.userprefs
 12 | 
 13 | # Build results
 14 | [Dd]ebug/
 15 | [Dd]ebugPublic/
 16 | [Rr]elease/
 17 | [Rr]eleases/
 18 | x64/
 19 | x86/
 20 | bld/
 21 | [Bb]in/
 22 | [Oo]bj/
 23 | [Ll]og/
 24 | 
 25 | # Visual Studio 2015 cache/options directory
 26 | .vs/
 27 | # Uncomment if you have tasks that create the project's static files in wwwroot
 28 | #wwwroot/
 29 | 
 30 | # MSTest test Results
 31 | [Tt]est[Rr]esult*/
 32 | [Bb]uild[Ll]og.*
 33 | 
 34 | # NUNIT
 35 | *.VisualState.xml
 36 | TestResult.xml
 37 | 
 38 | # Build Results of an ATL Project
 39 | [Dd]ebugPS/
 40 | [Rr]eleasePS/
 41 | dlldata.c
 42 | 
 43 | # DNX
 44 | project.lock.json
 45 | project.fragment.lock.json
 46 | artifacts/
 47 | 
 48 | *_i.c
 49 | *_p.c
 50 | *_i.h
 51 | *.ilk
 52 | *.meta
 53 | *.obj
 54 | *.pch
 55 | *.pdb
 56 | *.pgc
 57 | *.pgd
 58 | *.rsp
 59 | *.sbr
 60 | *.tlb
 61 | *.tli
 62 | *.tlh
 63 | *.tmp
 64 | *.tmp_proj
 65 | *.log
 66 | *.vspscc
 67 | *.vssscc
 68 | .builds
 69 | *.pidb
 70 | *.svclog
 71 | *.scc
 72 | 
 73 | # Chutzpah Test files
 74 | _Chutzpah*
 75 | 
 76 | # Visual C++ cache files
 77 | ipch/
 78 | *.aps
 79 | *.ncb
 80 | *.opendb
 81 | *.opensdf
 82 | *.sdf
 83 | *.cachefile
 84 | *.VC.db
 85 | *.VC.VC.opendb
 86 | 
 87 | # Visual Studio profiler
 88 | *.psess
 89 | *.vsp
 90 | *.vspx
 91 | *.sap
 92 | 
 93 | # TFS 2012 Local Workspace
 94 | $tf/
 95 | 
 96 | # Guidance Automation Toolkit
 97 | *.gpState
 98 | 
 99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 | 
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 | 
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 | 
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 | 
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 | 
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 | 
122 | # Web workbench (sass)
123 | .sass-cache/
124 | 
125 | # Installshield output folder
126 | [Ee]xpress/
127 | 
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 | 
138 | # Click-Once directory
139 | publish/
140 | 
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 | 
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 | 
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 | 
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 | 
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 | 
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 | 
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 | 
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 | 
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 | 
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 | 
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 | 
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 | 
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 | 
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 | 
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 | 
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 | 
231 | # Visual Studio 6 build log
232 | *.plg
233 | 
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 | 
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 | 
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 | 
249 | # FAKE - F# Make
250 | .fake/
251 | 
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 | 
256 | # CodeRush
257 | .cr/
258 | 
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
262 | /src/dotnetCampus.SourceYard/Properties/launchSettings.json
263 | 
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
 1 | 
 2 |   
 3 |   
 4 |     $(MSBuildThisFileDirectory)bin\$(Configuration)
 5 |     dotnet-campus
 6 |     dotnet-campus
 7 |     latest
 8 |     false
 9 |     
10 |     false
11 |     Add a NuGet package only for dll reference? By using dotnetCampus.SourceYard, you can pack a NuGet package with source code. By installing the new source code package, all source codes behaviors just like it is in your project.
12 |     Copyright (c) 2019-2021 dotnet-campus
13 |     https://github.com/dotnet-campus/dotnetCampus.SourceYard
14 |     https://github.com/dotnet-campus/dotnetCampus.SourceYard.git
15 |     git
16 |     source;dotnet;nuget;msbuild
17 |     MIT
18 |   
19 | 
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2018-2022 dotnet campus
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # dotnetCampus.SourceYard
 2 | 
 3 | | Build | NuGet |
 4 | |--|--|
 5 | ||[](https://www.nuget.org/packages/dotnetCampus.SourceYard)|
 6 | 
 7 | Add a NuGet package only for dll reference? By using dotnetCampus.SourceYard, you can pack a NuGet package with source code. By installing the new source code package, all source codes behaviors just like it is in your project.
 8 | 
 9 | ## Getting Started
10 | 
11 | ### Packing a source NuGet package
12 | 
13 | Using NuGet tool to install [dotnetCampus.SourceYard](https://www.nuget.org/packages/dotnetCampus.SourceYard) to your project
14 | 
15 | ```
16 | PM> Install-Package dotnetCampus.SourceYard 
17 | ```
18 | 
19 | Or
20 | 
21 | ```
22 | dotnet add package dotnetCampus.SourceYard
23 | ```
24 | 
25 | And then you should build your project and you will find the `*.Source.version.nupkg` file in your package output folder
26 | 
27 | **Remark**
28 | 
29 | The package with 0.1.19035-alpha version will break the double package reference project.
30 | 
31 | If you want to support the double package reference project, you can use the package with 0.1.19033-alpha version.
32 | 
33 | ## Documentation
34 | 
35 | [简体中文](README.zh-cn.md)
36 | 
37 | [NuGet shared source packages Microsoft Docs](https://docs.microsoft.com/en-us/dotnet/standard/library-guidance/dependencies#nuget-shared-source-packages )
38 | 
39 | ## Contributing
40 | 
41 | [](https://github.com/dotnet-campus/SourceYard/pulls)
42 | 
43 | If you would like to contribute, feel free to create a [Pull Request](https://github.com/dotnet-campus/SourceYard/pulls), or give us [Bug Report](https://github.com/dotnet-campus/SourceYard/issues/new).
44 | 
45 | ## Roadmap
46 | 
47 | Check out this [Roadmap](https://github.com/dotnet-campus/SourceYard/projects/1) to learn about our development plans for 2021.
48 | 
49 | ## Thanks
50 | 
51 | - [@Zhuangkh](https://github.com/Zhuangkh)
--------------------------------------------------------------------------------
/README.zh-cn.md:
--------------------------------------------------------------------------------
 1 | # SourceYard 源码包
 2 | 
 3 | | Build | NuGet |
 4 | |--|--|
 5 | ||[](https://www.nuget.org/packages/dotnetCampus.SourceYard)|
 6 | 
 7 | SourceYard 提供制作源代码的 Nuget 包的方法,制作出来的源代码包可以被安装到任意的源代码兼容的项目。最后会合并到被安装的项目的程序集。
 8 | 
 9 | 通过 SourceYard 可以分发简单的工具库,同时可以有效减少 DLL 的数量从而提升应用程序启动性能。因为 SourceYard 制作的是源代码包,制作出来的包具备良好的兼容性,通过宏等方法可以做到在各个平台使用相同的 Nuget 库。
10 | 
11 | ## 快速入门
12 | 
13 | 在项目中使用 NuGet 安装 [SourceYard](https://www.nuget.org/packages/dotnetCampus.SourceYard) 完成之后的每次编译生成,都可以在输出文件夹找到生成的 xx.source.1.0.0.nupkg 源代码包文件
14 | 
15 | 将源代码包文件提交到 NuGet 源上,可以将此源代码包作为和普通的 NuGet 包一样在其他项目安装使用
16 | 
17 | 以下是一个例子
18 | 
19 | 创建一个空白的库程序
20 | 
21 | ```
22 | dotnet new console -o Foo
23 | ```
24 | 
25 | 在创建的项目里面安装 SourceYard 库
26 | 
27 | ```
28 | cd Foo
29 | dotnet add package dotnetCampus.SourceYard
30 | ```
31 | 
32 | 运行 dotnet build 命令进行编译,编译完成可以在 `bin\debug` 文件夹可以找到打包的源代码包
33 | 
34 | **注意**
35 | 
36 | 版本号是 0.1.19035-alpha 将会影响双包项目的使用,如需支持双包的项目请采用 0.1.19033-alpha 版本
37 | 
38 | ## 文档
39 | 
40 | [中文文档](./docs/zh-cn)
41 | 
42 | [微软官方文档 NuGet 共享源代码包](https://docs.microsoft.com/zh-cn/dotnet/standard/library-guidance/dependencies#nuget-shared-source-packages )
43 | 
44 | ## 例子
45 | 
46 | [例子代码](./sample)
47 | 
48 | ## 开源社区
49 | 
50 | 如果你希望参与贡献,欢迎 [Pull Request](https://github.com/dotnet-campus/SourceYard/pulls),或给我们 [报告 Bug](https://github.com/dotnet-campus/SourceYard/issues/new)
51 | 
52 | ## 规划
53 | 
54 | 查看[这个页面](https://github.com/dotnet-campus/SourceYard/projects/1) 来了解我们 2020 年的开发计划
55 | 
56 | ## 授权协议
57 | 
58 | [](https://github.com/dotnet-campus/SourceYard/blob/master/LICENSE)
--------------------------------------------------------------------------------
/build/Version.props:
--------------------------------------------------------------------------------
1 | 
2 |   
3 |     0.1.19393-alpha13
4 |   
5 | 
6 | 
--------------------------------------------------------------------------------
/docs/en-us/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-campus/SourceYard/3480efbb3afe425a82f34d46210be39ad9b40e63/docs/en-us/README.md
--------------------------------------------------------------------------------
/docs/zh-cn/2018-09-29-20-36-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-campus/SourceYard/3480efbb3afe425a82f34d46210be39ad9b40e63/docs/zh-cn/2018-09-29-20-36-48.png
--------------------------------------------------------------------------------
/docs/zh-cn/AttachFile.md:
--------------------------------------------------------------------------------
 1 | # 附加文件
 2 | 
 3 | 将额外的文件加入到 SourceYard 源代码包
 4 | 
 5 | 加入某个文件夹的所有文件的方法如下
 6 | 
 7 | ```
 8 |   
 9 |     
10 |   
11 | ```
--------------------------------------------------------------------------------
/docs/zh-cn/Behavior.md:
--------------------------------------------------------------------------------
 1 | # 行为和配置
 2 | 
 3 | ## 术语
 4 | 
 5 | 源代码包: 将源代码打包到 NuGet 文件,也就是 SourceYard 工具的输出文件
 6 | 
 7 | 库项目: 用于打出源代码包的项目
 8 | 
 9 | 目标项目: 安装上某个源代码包的项目
10 | 
11 | ## 特殊配置
12 | 
13 | 在 SourceYard 打出的源代码包中,可以通过一些特殊的配置实现源代码包特殊的功能
14 | 
15 | ### DisableSourcePackageAutoPrivateAssets
16 | 
17 | 禁止自动配置目标全部源代码包自动设置 PrivateAssets 属性,默认的源代码将会自动添加如下代码
18 | 
19 | ```xml
20 |   
21 |     
22 |     
23 |     
24 |       all
25 |       all
26 |     
27 |   
28 | ```
29 | 
30 | 可以通过在 `目标项目` 上设置 DisableSourcePackageAutoPrivateAssets 属性为 true 禁用当前项目全部安装的源代码包自动设置
31 | 
32 | 以上的 `#(PackageId)` 就是对应的安装的源代码包,如 `TheLib.Source` 等
33 | 
34 | 如需要对具体某个源代码包进行配置,请自行设置更新覆盖即可
--------------------------------------------------------------------------------
/docs/zh-cn/DefaultIgnoreFile.md:
--------------------------------------------------------------------------------
 1 | # 默认忽略的文件和文件夹
 2 | 
 3 | ```csharp
 4 |         /// 
 5 |         /// 忽略的文件夹列表
 6 |         /// 
 7 |         private static IList IgnoreFolderList { get; } = new List()
 8 |         {
 9 |             ".vs", "bin", "obj", ".git", "x64", "x86"
10 |         };
11 | 
12 |         /// 
13 |         /// 忽略的文件后缀列表
14 |         /// 
15 |         private static IList IgnoreFileEndList { get; } = new List()
16 |         {
17 |             ".csproj.DotSettings", ".suo", ".user", ".sln.docstates", 
18 |             ".nupkg",
19 |             // 忽略原因请看 https://github.com/dotnet-campus/SourceYard/issues/98
20 |             "launchSettings.json"
21 |         };
22 | ```
--------------------------------------------------------------------------------
/docs/zh-cn/IncludeSourceYardPackageReference.md:
--------------------------------------------------------------------------------
 1 | # 引用源代码包依赖的原理
 2 | 
 3 | 在 `$(PackageId).props` 文件,也就是会在打包的时候,放在打出的源代码包,作为对应的源代码包的 Build 文件夹里面控制构建的 props 文件,在这个文件里面将当前源代码包的包 Id 加入到 SourceYardPackageReference 属性里面,如下面代码
 4 | 
 5 | ```xml
 6 |     
 7 |         
 8 |         $(SourceYardPackageReference);#(PackageId)
 9 |     
10 | ```
11 | 
12 | 这样在其他的项目,安装了源代码包,就可以通过 SourceYardPackageReference 属性了解当前项目安装了哪些源代码包
13 | 
14 | 例如有项目 A 安装了 B 源代码包,那么通过 SourceYardPackageReference 属性就能拿到 B 源代码包
15 | 
16 | 在将安装了源代码包的项目打包为源代码包时,例如将上面的 A 项目打包为源代码包时,想要添加 B 源代码包的引用依赖,就可以通过 SourceYardPackageReference 属性拿到当前 A 项目安装的源代码包,将这些源代码加入到依赖中
17 | 
18 | 添加源代码包依赖的逻辑放在 Core.targets 里,将 SourceYardPackageReference 属性写入到 SourceYardPackageReferenceFile 文件里面
19 | 
20 | ```xml
21 |     
22 | ```
23 | 
24 | 这个 SourceYardPackageReferenceFile 文件将会在 BuildProps 里面读取然后加入引用依赖
--------------------------------------------------------------------------------
/docs/zh-cn/README.md:
--------------------------------------------------------------------------------
 1 | # SourceYard 源码包
 2 | 
 3 | [SourceYard](about.md) 是[开源](https://github.com/dotnet-campus/SourceYard/blob/master/LICENSE)的 NuGet 源码包制作工具。它本质上也是一个 NuGet 包,当你将其安装到你的项目中后,可以为你的项目打出一个不同于原生 NuGet 包的特殊包,此包仅包含你项目中的源码而没有 dll 引用。
 4 | 
 5 | SourceYard 适用于 .NET 项目,无论是 .NET Core 还是 .NET Framework 或者是 .NET Standard。实际上它是一个用于开发阶段使用的 NuGet 包,所以也几乎可以无视所用的平台,只要你的开发环境中具有 .NET Core 运行时即可。
 6 | 
 7 | ## 上手 SourceYard
 8 | 
 9 | [SourceYard](https://www.nuget.org/packages/SourceYard/) 已发布到 [nuget.org](https://nuget.org/)。
10 | 
11 | 在 Visual Studio 项目中,打开 NuGet 包管理器,搜索 SourceYard,将其安装。当你开始编译项目的时候,即可以在输出目录下找到 `*.Source.nupkg` 包,这便是源码包。
12 | 
13 | 关于如何打一个源码包以及如何安装和使用源码包,请阅读:
14 | 
15 | - [入门](get-started.md)
16 | 
17 | 
--------------------------------------------------------------------------------
/docs/zh-cn/SourceYardExcludeFileItem.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-campus/SourceYard/3480efbb3afe425a82f34d46210be39ad9b40e63/docs/zh-cn/SourceYardExcludeFileItem.md
--------------------------------------------------------------------------------
/docs/zh-cn/SourceYardExcludePackageReference.md:
--------------------------------------------------------------------------------
 1 | # SourceYardExcludePackageReference
 2 | 
 3 | 排除的依赖引用
 4 | 
 5 | 在打源代码包的时候,有一些 NuGet 引用依赖不期望被加入源代码的依赖,以提升源代码包的兼容性
 6 | 
 7 | 此时可以采用 SourceYardExcludePackageReference 机制,在 SourceYardExcludePackageReference 项里面添加的 NuGet 包 Id 内容,将不会被加入源代码包引用依赖
 8 | 
 9 | 例如有项目 A 引用了两个 NuGet 包,分别是 B 和 C 库
10 | 
11 | ```xml
12 |   
13 |     
14 |     
15 |   
16 | ```
17 | 
18 | 而项目 A 不期望打出的源代码包,包含了 B 和 C 库的依赖。可以在项目文件里面添加 SourceYardExcludePackageReference 列表,如下面代码
19 | 
20 | ```xml
21 |   
22 |     
23 |     
24 |   
25 | ```
26 | 
27 | 此时打包出来的源代码包将不会包含 B 和 C 库的依赖
--------------------------------------------------------------------------------
/docs/zh-cn/about.md:
--------------------------------------------------------------------------------
1 | # 关于 SourceYard
2 | 
3 | SourceYard 具有如下特点:
4 | 
5 | - 将源代码打包到 NuGet 包中
6 | - 和安装其他 NuGet 包一样安装,无须额外的安装知识
7 | - 可以直接跳转源代码且可编辑调试断点
--------------------------------------------------------------------------------
/docs/zh-cn/get-started.md:
--------------------------------------------------------------------------------
 1 | # 入门
 2 | 
 3 | 源码包的使用分为两个部分:
 4 | 
 5 | 1. 源码包打包
 6 | 1. 安装和使用源码包
 7 | 
 8 | ## 源码包打包
 9 | 
10 | 我们现在从零开始创建一个项目,然后将其打包成源码包。
11 | 
12 | ### 第一步:新建一个项目,或者打开现有项目
13 | 
14 | 创建项目是 Visual Studio 开发的必备步骤,所以这里只做简单描述。
15 | 
16 | 
17 | 
18 | 在项目中,我们只新建一个简单的类型 `Foo` 用来演示:
19 | 
20 | ```csharp
21 | using System;
22 | 
23 | namespace dotnetCampus.Demo.Library
24 | {
25 |     /// 
26 |     /// This class is packaged as a source reference so it will be compiled into your own project.
27 |     /// 
28 |     public class Foo
29 |     {
30 |         /// 
31 |         /// Print hello to the specifed .
32 |         /// 
33 |         /// The name which  will say hello to.
34 |         public void PrintHello(string name)
35 |         {
36 |             Console.WriteLine($"Hello {name}");
37 |         }
38 |     }
39 | }
40 | ```
41 | 
42 | 项目中其实也只有这一个类而已:
43 | 
44 | ```
45 | - dotnetCampus.Demo.Library.csproj
46 | - Foo.cs
47 | ```
48 | 
49 | ## 安装和使用源代码打包
50 | 
51 | 可以通过命令行或 VisualStudio 的 NuGet 管理器安装 [SourceYard](https://www.nuget.org/packages/dotnetCampus.SourceYard)
52 | 
53 | 在安装完成之后,不需要任何配置,请右击项目进行编译
54 | 
55 | 编译完成可以在输出路径,如 `bin\debug` 看到 `dotnetCampus.Demo.Library.Source.1.0.0.nupkg` 源代码包
56 | 
57 | ## 使用源码包
58 | 
59 | 再次新建或打开一个项目,接下来演示在这个项目安装和使用上一步打出来的源代码包
60 | 
61 | 先在 VisualStudio 设置 NuGet 添加 `dotnetCampus.Demo.Library.Source.1.0.0.nupkg` 所在的文件夹
62 | 
63 | 此时就可以在项目里面通过 NuGet 安装 dotnetCampus.Demo.Library.Source 库
64 | 
65 | 尝试在新打开的项目里面使用 `dotnetCampus.Demo.Library.Foo` 方法
66 | 
67 | ```csharp
68 |             var foo = new dotnetCampus.Demo.Library.Foo();
69 |             foo.PrintHello("dotnet campus");
70 | ```
71 | 
72 | 尝试运行项目,将发现可以执行到 PrintHello 方法,同时支持断点调试到方法里面代码
73 | 
74 | 打开项目的输出文件夹,可以看到在文件夹里面不存在 `dotnetCampus.Demo.Library.dll` 因为此时源代码包是作为源代码引用
75 | 
76 | 例子用到的源代码参见 [sample](../../sample/App)
--------------------------------------------------------------------------------
/dotnetCampus.SourceYard.sln:
--------------------------------------------------------------------------------
 1 | 
 2 | Microsoft Visual Studio Solution File, Format Version 12.00
 3 | # Visual Studio Version 16
 4 | VisualStudioVersion = 16.0.29503.13
 5 | MinimumVisualStudioVersion = 10.0.40219.1
 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnetCampus.SourceYard", "src\dotnetCampus.SourceYard\dotnetCampus.SourceYard.csproj", "{E0E10F18-8AB9-4DC5-A68C-17726D619F24}"
 7 | EndProject
 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{075C3F7B-E00A-49D7-9D48-7F7DE6E2D4BC}"
 9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{75DA54C8-4888-4347-AF63-8E4C2CFB4D2C}"
11 | 	ProjectSection(SolutionItems) = preProject
12 | 		.gitattributes = .gitattributes
13 | 		.gitignore = .gitignore
14 | 		Directory.Build.props = Directory.Build.props
15 | 		LICENSE = LICENSE
16 | 		README.md = README.md
17 | 		build\Version.props = build\Version.props
18 | 	EndProjectSection
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnetCampus.SourceYard.Tests", "tests\dotnetCampus.SourceYard.Tests\dotnetCampus.SourceYard.Tests.csproj", "{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE}"
21 | EndProject
22 | Global
23 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | 		Debug|Any CPU = Debug|Any CPU
25 | 		Release|Any CPU = Release|Any CPU
26 | 	EndGlobalSection
27 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | 		{E0E10F18-8AB9-4DC5-A68C-17726D619F24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | 		{E0E10F18-8AB9-4DC5-A68C-17726D619F24}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | 		{E0E10F18-8AB9-4DC5-A68C-17726D619F24}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | 		{E0E10F18-8AB9-4DC5-A68C-17726D619F24}.Release|Any CPU.Build.0 = Release|Any CPU
32 | 		{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | 		{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | 		{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | 		{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE}.Release|Any CPU.Build.0 = Release|Any CPU
36 | 	EndGlobalSection
37 | 	GlobalSection(SolutionProperties) = preSolution
38 | 		HideSolutionNode = FALSE
39 | 	EndGlobalSection
40 | 	GlobalSection(NestedProjects) = preSolution
41 | 		{40CA62ED-6DFF-4A65-93D4-A91AB5DCF9DE} = {075C3F7B-E00A-49D7-9D48-7F7DE6E2D4BC}
42 | 	EndGlobalSection
43 | 	GlobalSection(ExtensibilityGlobals) = postSolution
44 | 		SolutionGuid = {7117963B-299E-4A6F-AFC6-D82B83656776}
45 | 	EndGlobalSection
46 | EndGlobal
47 | 
--------------------------------------------------------------------------------
/dotnetCampus.SourceYard.sln.DotSettings:
--------------------------------------------------------------------------------
1 | 
2 | 	SDK
3 | 	True
4 | 	True
5 | 	True
--------------------------------------------------------------------------------
/sample/App/AppUsingDll/AppUsingDll.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     Exe
 5 |     net45
 6 |   
 7 | 
 8 |   
 9 |     
10 |   
11 | 
12 | 
13 | 
--------------------------------------------------------------------------------
/sample/App/AppUsingDll/Program.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using TheLib;
 3 | 
 4 | namespace AppUsingDll
 5 | {
 6 |     class Program
 7 |     {
 8 |         static void Main(string[] args)
 9 |         {
10 |             var money = new Money(12312);
11 |             Console.WriteLine(money.ToCapital());
12 |             Console.ReadLine();
13 |         }
14 |     }
15 | }
16 | 
--------------------------------------------------------------------------------
/sample/App/AppUsingSource/AppUsingSource.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 |   
 3 | 
 4 |   
 5 |     net45;net5.0
 6 |     Exe
 7 |     
 8 |   
 9 | 
10 |   
11 |     
12 |   
13 |   
14 | 
15 | 
--------------------------------------------------------------------------------
/sample/App/AppUsingSource/Program.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Windows;
 3 | using TheLib;
 4 | 
 5 | namespace AppUsingSource
 6 | {
 7 |     class Program
 8 |     {
 9 |         static void Main(string[] args)
10 |         {
11 |             var money = new Money(12312);
12 |             var v = (money, "123");
13 |             Console.WriteLine(v);
14 | 
15 | #if NET45
16 |             var dependencyObject = new DependencyObject();
17 | #endif
18 | 
19 |             Console.WriteLine(money.ToCapital());
20 |             Console.ReadLine();
21 |         }
22 |     }
23 | }
24 | 
--------------------------------------------------------------------------------
/sample/App/AppUsingSource/SourceProject/.gitignore:
--------------------------------------------------------------------------------
1 | *.Source.SourceProject.props
--------------------------------------------------------------------------------
/sample/App/TheLib/Money.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.Text;
  4 | 
  5 | namespace TheLib
  6 | {
  7 |     /// 
  8 |     /// 人民币转大写
  9 |     /// 
 10 |     public class Money
 11 |     {
 12 |         public Money(double money)
 13 |         {
 14 |             _money = money;
 15 |         }
 16 | 
 17 |         public string ToCapital()
 18 |         {
 19 |             if (Math.Abs(_money) < 0.0001)
 20 |             {
 21 |                 return "零元";
 22 |             }
 23 | 
 24 |             var str = GetIntPart();
 25 |             GetDecimalPart(str);
 26 |             return str.ToString();
 27 |         }
 28 | 
 29 |         private static readonly List Uppers = new List()
 30 |         {
 31 |             '零',
 32 |             '壹',
 33 |             '贰',
 34 |             '叁',
 35 |             '肆',
 36 |             '伍',
 37 |             '陆',
 38 |             '柒',
 39 |             '捌',
 40 |             '玖'
 41 |         };
 42 | 
 43 |         private static readonly List Units = new List()
 44 |         {
 45 |             '分',
 46 |             '角'
 47 |         };
 48 | 
 49 |         private static readonly List Grees = new List()
 50 |         {
 51 |             '元',
 52 |             '拾',
 53 |             '佰',
 54 |             '仟',
 55 |             '万',
 56 |             '拾',
 57 |             '佰',
 58 |             '仟',
 59 |             '亿',
 60 |             '拾',
 61 |             '佰',
 62 |             '仟',
 63 |             '万',
 64 |             '拾',
 65 |             '佰'
 66 |         };
 67 | 
 68 |         private readonly double _money;
 69 | 
 70 |         private StringBuilder GetIntPart()
 71 |         {
 72 |             StringBuilder str = new StringBuilder();
 73 |             var money = _money;
 74 | 
 75 |             for (int i = 0; money > 0.99999; i++)
 76 |             {
 77 |                 var n = (int)(money % 10);
 78 |                 str.Insert(0, Grees[i]);
 79 |                 str.Insert(0, Uppers[n]);
 80 |                 money = money / 10;
 81 |                 money = money - (n / 10.0);
 82 |             }
 83 | 
 84 |             str = str.Replace("零亿", "亿零");
 85 |             str = str.Replace("零万", "万零");
 86 | 
 87 |             str = str.Replace("零拾", "零");
 88 |             str = str.Replace("零佰", "零");
 89 |             str = str.Replace("零仟", "零");
 90 | 
 91 |             str = str.Replace("零零", "零");
 92 |             str = str.Replace("零零", "零");
 93 | 
 94 |             str = str.Replace("零亿", "亿");
 95 |             str = str.Replace("零万", "万");
 96 |             str = str.Replace("零元", "元");
 97 | 
 98 |             return str;
 99 |         }
100 | 
101 |         private void GetDecimalPart(StringBuilder str)
102 |         {
103 |             var money = _money * 100;
104 |             for (int i = 0; i < 2; i++)
105 |             {
106 |                 var n = (int)(money % 10);
107 |                 if (n != 0)
108 |                 {
109 |                     str.Insert(0, Units[i]);
110 |                     str.Insert(0, Uppers[n]);
111 |                 }
112 | 
113 |                 money = money / 10;
114 |             }
115 |         }
116 |     }
117 | }
118 | 
--------------------------------------------------------------------------------
/sample/App/TheLib/Resource/F1.md:
--------------------------------------------------------------------------------
1 | # F1
--------------------------------------------------------------------------------
/sample/App/TheLib/Resource/F2.md:
--------------------------------------------------------------------------------
1 | # F2
--------------------------------------------------------------------------------
/sample/App/TheLib/TheLib.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     net45
 5 |     true
 6 |   
 7 | 
 8 |   
 9 |     
10 |       all
11 |       runtime; build; native; contentfiles; analyzers
12 |     
13 |   
14 | 
15 |   
16 |   
17 |   
18 |   
19 | 
20 |   
21 |     
22 |     
23 |   
24 | 
25 |   
26 |     
27 |   
28 | 
29 |   
39 | 
40 |   
41 |     
42 |     
43 |   
44 | 
45 | 
--------------------------------------------------------------------------------
/sample/App/TheLib/foo.coin:
--------------------------------------------------------------------------------
1 | > Foo
--------------------------------------------------------------------------------
/sample/App/TheLib/foo1.coin:
--------------------------------------------------------------------------------
1 | > Foo
--------------------------------------------------------------------------------
/sample/Directory.Build.props:
--------------------------------------------------------------------------------
 1 | 
 2 |   
 3 |   
 4 |     $(MSBuildThisFileDirectory)bin\$(Configuration)
 5 |     $(MSBuildThisFileDirectory)bin\app\$(MSBuildProjectName)\
 6 |     dotnet campus
 7 |     lindexi;吕毅
 8 |     https://github.com/dotnet-campus/SourceYard
 9 |     git
10 |     https://github.com/dotnet-campus/SourceYard
11 |     Copyright © 2018-2021 dotnet campus All Rights Reserved.
12 |     SourceYard
13 |   
14 | 
--------------------------------------------------------------------------------
/sample/README.md:
--------------------------------------------------------------------------------
  1 | # SourceYard 制作源代码包
  2 | 
  3 | 本文带大家走进SourceYard开发之旅
  4 | 
  5 | 
  6 | 在项目开发中,将一个大的项目拆为多个小项目解耦,减少模块之间的耦合。因为如果将代码放在一起,即使有团队的约束,但只要能写出的代码就会有小伙伴写出,很快就发现各个模块耦合的代码很多。但是对一个项目的拆分会让拆分出来的每一个项目都编译出一个 dll 增加运行文件的启动时间。
  7 | 
  8 | 在开发中,常常会用到很多工具类,这些小轮子很多的功能基本就只有一个类,如何对这些小轮子进行管理?通过复制代码还是通过 Nuget 管理?
  9 | 
 10 | 
 11 | 
 12 | 
 13 | 如果使用复制代码的方式,很难知道从哪里复制代码,如果在很多项目都复制了代码,发现原来的代码存在一些虫子,很难修改所有复制代码的项目。通过传统 Nuget 的方式可以方便管理工具的更新,和引入工具,同时会将每个小轮子打包成一个 dll 这样会引入很多 dll 让软件启动的速度和运行的速度降低。关于 dll 数量和启动时间的测试请看 [C# 程序集数量对软件启动性能的影响](https://lindexi.gitee.io/post/C-%E7%A8%8B%E5%BA%8F%E9%9B%86%E6%95%B0%E9%87%8F%E5%AF%B9%E8%BD%AF%E4%BB%B6%E5%90%AF%E5%8A%A8%E6%80%A7%E8%83%BD%E7%9A%84%E5%BD%B1%E5%93%8D.html ) 介绍了程序集数量对软件启动性能的影响,运行的性能是在引用某个 dll 方法的时候需要加载这个 dll 降低速度。
 14 | 
 15 | 有小伙伴问,为何不将所有的工具放在一个大的项目,这样每次只需要更新大项目的 Nuget 就可以,这样就可以解决引入dll的数量和管理小工具。
 16 | 
 17 | 虽然将很多的工具放在一个程序集做一个 Nuget 的方式看起来不错,但是只是在很小的项目同时不能维护太久,在我现在的团队有一个库,这个库就是用来放小工具,但是在经过了一段时间,发现基本上所有小伙伴在不知道要将类放在哪个地方的时候,就会放在这个程序集里。同时因为所有工具都在一个程序集里,所有小工具都在相互引用。在我想要修复某个小工具的功能的时候,发现在这个程序集内这个工具已经有 99 引用,其中还有不少地方依赖 bug 编程,这时维护这样一个程序集的成功非常高,同时无法组织小伙伴不断将含义不明确的类放在这个程序集(这里不是在讨论代码审查问题,在我现在的团队是有明确的代码审查,然而没有人能说清这个程序集的功能),所以这就是为什么不建议所有小工具放在一个程序集的原因。另外如果都将代码放在一个程序集,用于分享也是比较难,有小伙伴向我要一些工具,假设我都放在一个程序集里,那么我只能通过拷贝代码的方式给他,因为我不确定工具程序集里面是否有不能对外发布的内容,但如果是 SourceYard 的方法,作为源代码包可以将小伙伴需要的工具发布到 Nuget.org 请他去安装。
 18 | 
 19 | 当然将工具放在一个工具程序集也不是没有优点,因为所有的工具都在一个程序集里面,小伙伴可以方便找到自己需要的类,而不是通过 Nuget 的方式去寻找安装。同时如果有一个项目多个程序集需要相同的工具,可以同时依赖工具程序集,减少创建出来的 dll 文件里重复代码。
 20 | 
 21 | 解决上面的两个问题的方法是通过 SourceYard 的方法,使用 SourceYard 不但可以解决项目解耦创建了很多个项目让很多个项目编译出来的 dll 太多让软件启动性能降低,同时解决小工具类太多的问题,还可以解决代码兼容的问题。
 22 | 
 23 | ## 控制台项目
 24 | 
 25 | 创建一个 dotnet core 项目进行开发,这里创建一个 dotnet core 项目主要是因为创建出来的项目清真
 26 | 
 27 | 假设有一个需求是做一个工具,这个工具的功能是用户输入数字,转换为人民币金额大写,听起来这个功能很简单,当然在本文就不会详细告诉大家这个工具的代码。
 28 | 
 29 | 
 30 | 
 31 | 
 32 | 
 33 | 在我之前的博客[C# 金额转中文大写](https://lindexi.gitee.io/post/C-%E9%87%91%E9%A2%9D%E8%BD%AC%E4%B8%AD%E6%96%87%E5%A4%A7%E5%86%99.html )已经有了代码,可以从[码云复制](https://gitee.com/lindexi/codes/w6bxlue9o14rv5nscjyhf20 ) 复制的代码因为没有命名空间,需要手动添加,于是现在就创建了一个项目,这个项目包含一个类。
 34 | 
 35 | 
 36 | 
 37 | 
 38 | 
 39 | 使用 SourceYard 很简单,只需要在 TheLib 项目管理 Nuget 安装 SourceYard 就可以
 40 | 
 41 | 
 42 | 
 43 | 
 44 | 
 45 | 现在 SourceYard 还没正式发布,里面还存在一些坑,但是对于这么简单的项目已经可以使用。
 46 | 
 47 | 如果对 SourceYard 感兴趣,请在 [github](https://github.com/dotnet-campus/SourceYard ) 关注
 48 | 
 49 | 右击 TheLib 的属性,在打包的页面勾选在版本中生成 Nuget 包,勾选之后重新编译就可以制作出 Nuget 包。但是请不要急,在打包页面还有很多东西需要填写,在[广州 .NET 微软技术俱乐部12月份活动](http://www.10tiao.com/html/391/201811/2654072986/1.html) 的演示中,我使用了[这个黑科技](https://lindexi.gitee.io/post/Roslyn-%E5%B0%86%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6%E6%94%BE%E5%9C%A8%E4%BD%A0%E7%9A%84%E9%A1%B9%E7%9B%AE%E6%96%87%E4%BB%B6%E5%A4%B9-%E6%97%A0%E8%AE%BA%E5%93%AA%E4%B8%AA%E6%8E%A7%E5%88%B6%E5%8F%B0%E9%A1%B9%E7%9B%AE%E9%83%BD%E4%BC%9A%E8%BE%93%E5%87%BA%E6%9E%97%E5%BE%B7%E7%86%99%E6%98%AF%E9%80%97%E6%AF%94.html )瞬间完成了所有属性,小伙伴如果还没学会这个黑科技就需要手动填写内容了,其实只有作者、公司、说明是必要的,其他的可以不写。
 50 | 
 51 | 
 52 | 
 53 | 
 54 | 
 55 | 如果需要将 TheLib 修改为 dotnet framework 的项目,只需要右击编辑 csproj 文件就可以,在[理解 C# 项目 csproj 文件格式的本质和编译流程](https://walterlv.gitee.io/post/understand-the-csproj.html )和[广州 .NET 微软技术俱乐部12月份活动](http://www.10tiao.com/html/391/201811/2654072986/1.html) 吕毅都讲了项目的格式,如果只需要修改 dotnet framework 不需要了解那么多,只需要在 TargetFramework 里面修改为 net45 就完成
 56 | 
 57 | ```
 58 | 
 59 | 
 60 |   
 61 |     net45
 62 |     true
 63 |   
 64 | 
 65 |   
 66 |     
 67 |       all
 68 |       runtime; build; native; contentfiles; analyzers
 69 |     
 70 |   
 71 | 
 72 | 
 73 | ```
 74 | 
 75 | 现在右击项目重新编译就可以打出 Nuget 包,在使用新的项目格式,默认的 dotnet core 项目就是这么简单,具体请看[VisualStudio 使用新项目格式快速打出 Nuget 包](https://lindexi.gitee.io/post/VisualStudio-%E4%BD%BF%E7%94%A8%E6%96%B0%E9%A1%B9%E7%9B%AE%E6%A0%BC%E5%BC%8F%E5%BF%AB%E9%80%9F%E6%89%93%E5%87%BA-Nuget-%E5%8C%85.html )详细写了黑科技
 76 | 
 77 | 在输出的文件夹可以找到打包的 Nuget 文件
 78 | 
 79 | 
 80 | 
 81 | 
 82 | 
 83 | 文件可以通过 [Nuget 管理器](https://www.microsoft.com/store/productId/9WZDNCRDMDM3) 打开,这个文件可以在应用商店找到
 84 | 
 85 | 
 86 | 
 87 | 
 88 | 
 89 | 这里两个不同的文件,其他是传统的 Nuget 包,也就是 TheLib.1.0.2.nupkg 里面包含 dll 请打开文件很快就可以看到
 90 | 
 91 | 
 92 | 
 93 | 
 94 | 
 95 | 源代码的文件的格式也请小伙伴打开看一下,里面没有 dll 里面是代码,在安装这个文件就会引用代码,代码会编译在引用的项目。多个不同的源代码包会编译为一个程序集。
 96 | 
 97 | 
 98 | 
 99 | 
100 | 
101 | 虽然有 Nuget 文件但是还不知道这个文件能不能使用,创建两个不同的项目用来用这两个文件,因为刚才已经修改项目为 dotnet framework 的,就需要创建一个 dotnet framework 的项目
102 | 
103 | 
104 | 
105 | 
106 | 
107 | 右击项目管理 Nuget 引用本地的 Nuget 文件的文件夹,如我这里的 Nuget 文件是在 `D:\lindexi\SourceYard\bin\Debug` 文件夹下,我就需要添加这样的路径,请看图片
108 | 
109 | 
110 | 
111 | 
112 | 
113 | 这里的程序包源的名称是可以随意给的,程序员最难的就是命名,好在有[Whitman](https://www.microsoft.com/store/productId/9P8LNZRNJX85 ) 这个工具可以按下 ctrl+, 输入第一个字符为小写的变量,按下 ctrl+shift+, 输入第一个字符为大写的变量。现在这个工具已经从 dotnet framework 升级到 dotnet core 请看 [将基于 .NET Framework 的 WPF 项目迁移到基于 .NET Core 3 - walterlv](https://walterlv.gitee.io/post/migrate-wpf-project-from-dotnet-framework-to-dotnet-core.html ) 关于 WPF 怎么可以在 dotnet core 运行,微软已经将 WPF 的 dotnet core 开源,可以在 [github](https://github.com/dotnet/wpf ) 找到
114 | 
115 | 现在点击本地的源,如刚才命名为 TacaluTawnenai 的源就可以找到刚才的两个文件,如何选择本地的源?请看下图,点击程序包源的下拉就可以找到
116 | 
117 | 
118 | 
119 | 
120 | 
121 | 刚才创建的 dotnet framework 程序还是比较不清真的,先进行卸载,然后编辑 csproj 文件,可以看到这里的文件内容非常多,这是很不清真的。从刚才的 TheLib 文件里面拷贝 csproj 文件到 AppUsingDll 项目里,记得需要先去掉 SourceYard 的部分
122 | 
123 | ```
124 | 
125 | 
126 |   
127 |     net45
128 |     true
129 |   
130 | 
131 |   
132 |     
133 |       all
134 |       runtime; build; native; contentfiles; analyzers
135 |     
136 |   
137 | 
138 | 
139 | ```
140 | 
141 | 将上面不需要的部分,也就是引用 SourceYard 包的部分和 GeneratePackageOnBuild 去掉,现在剩下的代码很少
142 | 
143 | ```
144 | 
145 | 
146 |   
147 |     net45
148 |   
149 | 
150 | ```
151 | 
152 | 控制台项目需要做很小的修改,通过右击项目属性,在界面选择控制台
153 | 
154 | 
155 | 
156 | 
157 | 
158 | 如果此时进行编译会看到编译不通过,因为还需要删除 AssemblyInfo.cs 文件的很多代码,其实可以直接删除这个文件
159 | 
160 | 在这个项目需要安装 TheLib 库,安装的方式和安装其他的 Nuget 没有不同,通过本地的文件夹安装 Nuget 包和通过 Nuget 服务器安装没有不同,如果需要自己搭建 Nuget 服务器也是十分简单,请看[通过ProGet搭建一个内部的Nuget服务器 - 张善友 - 博客园](http://www.cnblogs.com/shanyou/p/5910250.html )我就帮小伙伴在10分钟内搭建 Nuget 服务器
161 | 
162 | 
163 | 
164 | 
165 | 
166 | 安装之后添加一点代码测试一下能否使用
167 | 
168 | ```csharp
169 |             var money = new Money(12312);
170 |             Console.WriteLine(money.ToCapital());
171 |             Console.ReadLine();
172 | ```
173 | 
174 | 这时运行一下,可以看到成功运行了。
175 | 
176 | 再创建一个项目,这个项目尝试使用 dotnet core 的项目
177 | 
178 | 
179 | 
180 | 
181 | 
182 | 右击项目管理 Nuget 安装源代码包,然后在主函数添加相同的测试代码
183 | 
184 | 
185 | 
186 | 
187 | 
188 | ```csharp
189 |         static void Main(string[] args)
190 |         {
191 |             var money = new Money(12312);
192 |             Console.WriteLine(money.ToCapital());
193 |             Console.ReadLine();
194 |         }
195 | ```
196 | 
197 | 现在尝试运行,可以看到和刚才的 dotnet framework 控制台输出相同
198 | 
199 | 但是有一点不相同的是,打开两个项目的输出文件夹,可以看到 dotnet framework 项目引用的是 dll 的方式,输出的文件夹有一个dll和一个exe 在 dotnet core 项目的输出文件夹只有一个 dll 因为默认的 dotnet core 输出的是 dll 源代码就放在相同的 dll 里
200 | 
201 | 
202 | 
203 | 
204 | 
205 | 
206 | 
207 | 
208 | 
209 | 这时就可以看到 SourceYard 的好处,通过 SourceYard 可以将源代码作为 Nuget 包,这样不但减少 dll 的数量,同时做到源代码的兼容。在之前,无论是PCL还是多项目方式的 Nuget 包管理多个不同平台的兼容难度比较大,但是通过 SourceYard 只要源代码可以兼容就可以安装。在本文的控制台的使用的库是 dotnet framework 4.5 但是控制台项目使用的是 dotnet core 2.1 的,这样都可以使用。
210 | 
211 | ## WPF 程序
212 | 
213 | 如果小伙伴觉得控制台还是太简单了,可以尝试使用桌面WPF程序,此时 WinForms 程序也是适合的。
214 | 
215 | 创建一个简单的 WPF 库,注意创建之后需要修改代码,修改项目格式为 VisualStudio 2017 格式
216 | 
217 | 在开始编辑之前,先创建一个用户控件,这里叫 InterestingControl 一个有趣的控件,同时删除 Properties 文件夹的所有文件
218 | 
219 | 
220 | 
221 | 
222 | 
223 | 相对来说,做 WPF 的库使用新项目格式要求对新的格式比较熟悉,所以请直接卸载项目,编辑一下项目文件,填入下面的代码
224 | 
225 | ```
226 | 
227 |   
228 |     $(MSBuildToolsPath)\Microsoft.CSharp.targets
229 |     net45;
230 |     Library
231 |     WpfUI
232 |     WpfUI
233 |     true
234 |   
235 |   
236 |     $(DefineConstants);WPF
237 |   
238 |  
239 |   
240 |     
241 |       %(Filename)
242 |     
243 |     
244 |       Designer
245 |       MSBuild:Compile
246 |     
247 | 
248 |     
249 |     
250 |     
251 |     
252 |     
253 |     
254 |     
255 |   
256 |  
257 |   
258 |     
259 |     
260 |     
261 |     
262 |     
263 |   
264 |  
265 |   
266 |     
267 |       all
268 |       runtime; build; native; contentfiles; analyzers
269 |     
270 |   
271 |  
272 |   
273 |     
274 |     
275 |     
276 |     
277 |     
278 |     
279 |     
280 |     
281 |     
282 |     
283 |     
284 |     
285 |   
286 |  
287 |   
288 |     
289 |       Code
290 |     
291 |   
292 |  
293 |   
294 |     
295 |   
296 |  
297 |   
298 |     
299 |       MSBuild:Compile
300 |     
301 |   
302 | 
303 | ```
304 | 
305 | 请根据实际的项目更改 AssemblyName 的值
306 | 
307 | 制作源代码包的方式和控制台的相同,只需要在 Nuget 安装 SourceYard 就可以,同样打开属性,和控制台一样
308 | 
309 | 
310 | 
311 | 
312 | 
313 | 现在右击重新编译,就可以在输出文件夹找到输出的两个 Nuget 包
314 | 
315 | 再创建一个 WPF 程序,通过设置本地的 Nuget 包的文件夹,安装源代码包,然后在界面使用刚才的用户控件,运行就可以发现成功使用了用户控件
316 | 
317 | 打开 WPF 程序的输出文件夹,可以发现这个文件夹里面只有一个 exe 源代码已经放在 exe 里
318 | 
319 | ## 调试
320 | 
321 | 在将项目制作 Nuget 包的时候,就有小伙伴吐槽在开发的时候,如果使用 Nuget 安装,很难进行调试,很难在 dll 里面添加断点,同时在调试的时候修改代码
322 | 
323 | 但是在使用 SourceYard 调试的时候,安装 Nuget 的库和调试本地的引用的代码是完全一样的,就使用上面的控制台调试
324 | 
325 | 例如需要无论用户输出的是什么返回的都是 林德熙是逗比
326 | 
327 | 细心的小伙伴会发现安装 SourceYard 之后,在项目会出现一个文件夹是 SourceProject 里面就有一个文件 TheLib.Source.SourceProject.props 打开这个文件可以看到下面的内容
328 | 
329 | ```
330 | 
331 | 
332 | 
333 |   
334 | 
335 |   
336 | 
337 |   
340 |   
341 |   
342 |   
345 | 
346 | 
347 | 
348 | ```
349 | 
350 | 这个文件里面有一些代码暂时无法使用,需要先做设置,首先设置 TheLibSourceFolder 这里表示源代码包的原始项目的文件夹,如 TheLib 的文件夹是 `C:\lindexi\SourceYard\TheLib` 请小心设置路径
351 | 
352 | 
353 | 
354 | 
355 | 
356 | 然后取消除了中文的注释,请看代码
357 | 
358 | ```
359 | 
360 | 
361 | 
362 |   
363 | 
364 |   
365 | 
366 |   
367 |     $(DefineConstants);TheLibSOURCE_REFERENCE
368 |   
369 | 
370 |   
371 |   
372 |     C:\lindexi\SourceYard\TheLib
373 |   
374 | 
375 | 
376 | 
377 | ```
378 | 
379 | 此时通过 ctrl+点击的方式可以进入 Money 文件,这时可以进行调试
380 | 
381 | 
382 | 
383 | 
384 | 
385 | 此时在这个函数下面返回林德熙是逗比
386 | 
387 | 
388 | 
389 | 
390 | 
391 | 按 F5 运行,可以看到输出的是 林德熙是逗比 也就是源代码已经修改
392 | 
393 | 打开 TheLib 的 Money.cs 文件可以发现里面的文件也同时被修改,也就是这个文件被两个项目引用,通过这个方法就和将项目引用的方式那样调试解决 dll 难以断点和修改代码
394 | 
395 | 如果不设置 TheLibSourceFolder 路径,也是可以调试文件,同样也可以在调试的时候修改代码,但是这时的代码是无法上传的,也就是只能在本地的缓存使用,在清空缓存之后,对代码的修改将会找不到
396 | 
397 | 因为 SourceYard 还在开发过程,代码开放在 [github](https://github.com/dotnet-campus/SourceYard ) 欢迎小伙伴贡献
398 |  
399 | 
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我[联系](mailto:lindexi_gd@163.com)。
400 | 
--------------------------------------------------------------------------------
/sample/Sample.sln:
--------------------------------------------------------------------------------
 1 | 
 2 | Microsoft Visual Studio Solution File, Format Version 12.00
 3 | # Visual Studio 15
 4 | VisualStudioVersion = 15.0.28307.136
 5 | MinimumVisualStudioVersion = 10.0.40219.1
 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{8EA1AC0A-75EA-4D9F-9D89-4AC8886EC9D0}"
 7 | 	ProjectSection(SolutionItems) = preProject
 8 | 		build\Version.props = build\Version.props
 9 | 	EndProjectSection
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "App", "App", "{F759FC49-18C9-4AA6-8D6B-7D151777A0E5}"
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppUsingDll", "App\AppUsingDll\AppUsingDll.csproj", "{457DCF08-D0FB-456A-A50C-663C991CFBC9}"
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TheLib", "App\TheLib\TheLib.csproj", "{AC631952-4B75-437B-9C9A-7A2D9FFD2712}"
16 | EndProject
17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppUsingSource", "App\AppUsingSource\AppUsingSource.csproj", "{E5BCA9B4-10EA-46A5-A252-86492962DBF0}"
18 | EndProject
19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WPF", "WPF", "{D44D4292-E398-4104-B15A-97DBFEFD2D88}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApp", "WPF\WpfApp\WpfApp.csproj", "{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfUI", "WPF\WpfUI\WpfUI.csproj", "{4CE66408-1FBD-45FC-9377-397456E877F1}"
24 | EndProject
25 | Global
26 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
27 | 		Debug|Any CPU = Debug|Any CPU
28 | 		Release|Any CPU = Release|Any CPU
29 | 	EndGlobalSection
30 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
31 | 		{457DCF08-D0FB-456A-A50C-663C991CFBC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | 		{457DCF08-D0FB-456A-A50C-663C991CFBC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | 		{457DCF08-D0FB-456A-A50C-663C991CFBC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
34 | 		{457DCF08-D0FB-456A-A50C-663C991CFBC9}.Release|Any CPU.Build.0 = Release|Any CPU
35 | 		{AC631952-4B75-437B-9C9A-7A2D9FFD2712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | 		{AC631952-4B75-437B-9C9A-7A2D9FFD2712}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | 		{AC631952-4B75-437B-9C9A-7A2D9FFD2712}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | 		{AC631952-4B75-437B-9C9A-7A2D9FFD2712}.Release|Any CPU.Build.0 = Release|Any CPU
39 | 		{E5BCA9B4-10EA-46A5-A252-86492962DBF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | 		{E5BCA9B4-10EA-46A5-A252-86492962DBF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | 		{E5BCA9B4-10EA-46A5-A252-86492962DBF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | 		{E5BCA9B4-10EA-46A5-A252-86492962DBF0}.Release|Any CPU.Build.0 = Release|Any CPU
43 | 		{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | 		{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | 		{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | 		{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8}.Release|Any CPU.Build.0 = Release|Any CPU
47 | 		{4CE66408-1FBD-45FC-9377-397456E877F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | 		{4CE66408-1FBD-45FC-9377-397456E877F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | 		{4CE66408-1FBD-45FC-9377-397456E877F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | 		{4CE66408-1FBD-45FC-9377-397456E877F1}.Release|Any CPU.Build.0 = Release|Any CPU
51 | 	EndGlobalSection
52 | 	GlobalSection(SolutionProperties) = preSolution
53 | 		HideSolutionNode = FALSE
54 | 	EndGlobalSection
55 | 	GlobalSection(NestedProjects) = preSolution
56 | 		{457DCF08-D0FB-456A-A50C-663C991CFBC9} = {F759FC49-18C9-4AA6-8D6B-7D151777A0E5}
57 | 		{AC631952-4B75-437B-9C9A-7A2D9FFD2712} = {F759FC49-18C9-4AA6-8D6B-7D151777A0E5}
58 | 		{E5BCA9B4-10EA-46A5-A252-86492962DBF0} = {F759FC49-18C9-4AA6-8D6B-7D151777A0E5}
59 | 		{F2A2F01B-8454-40DF-9E6B-A9DB4DFC58D8} = {D44D4292-E398-4104-B15A-97DBFEFD2D88}
60 | 		{4CE66408-1FBD-45FC-9377-397456E877F1} = {D44D4292-E398-4104-B15A-97DBFEFD2D88}
61 | 	EndGlobalSection
62 | 	GlobalSection(ExtensibilityGlobals) = postSolution
63 | 		SolutionGuid = {D994A34A-AF17-461B-B5C4-0DB24A11BFFD}
64 | 	EndGlobalSection
65 | EndGlobal
66 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/App.xaml:
--------------------------------------------------------------------------------
 1 | 
 6 |     
 7 |          
 8 |     
 9 | 
10 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/App.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Configuration;
 4 | using System.Data;
 5 | using System.Linq;
 6 | using System.Threading.Tasks;
 7 | using System.Windows;
 8 | 
 9 | namespace WpfApp
10 | {
11 |     /// 
12 |     /// App.xaml 的交互逻辑
13 |     /// 
14 |     public partial class App : Application
15 |     {
16 |         [STAThread]
17 |         private static void Main(string[] args)
18 |         {
19 |             var app = new App();
20 |             app.InitializeComponent();
21 |             app.Run();
22 |         }
23 |     }
24 | }
25 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/MainWindow.xaml:
--------------------------------------------------------------------------------
 1 | 
10 |     
11 |         
12 |     
13 | 
14 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | using System.Windows.Controls;
 8 | using System.Windows.Data;
 9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | 
16 | namespace WpfApp
17 | {
18 |     /// 
19 |     /// MainWindow.xaml 的交互逻辑
20 |     /// 
21 |     public partial class MainWindow : Window
22 |     {
23 |         public MainWindow()
24 |         {
25 |             InitializeComponent();
26 |         }
27 |     }
28 | }
29 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
 1 | using System.Runtime.InteropServices;
 2 | using System.Windows;
 3 | 
 4 | // 将 ComVisible 设置为 false 会使此程序集中的类型
 5 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
 6 | //请将此类型的 ComVisible 特性设置为 true。
 7 | [assembly: ComVisible(false)]
 8 | 
 9 | [assembly: ThemeInfo(
10 |     ResourceDictionaryLocation.None, //主题特定资源词典所处位置
11 |     //(未在页面中找到资源时使用,
12 |     //或应用程序资源字典中找到时使用)
13 |     ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
14 |     //(未在页面中找到资源时使用,
15 |     //、应用程序或任何主题专用资源字典中找到时使用)
16 | )]
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
 1 | //------------------------------------------------------------------------------
 2 | // 
 3 | //     此代码由工具生成。
 4 | //     运行时版本: 4.0.30319.42000
 5 | //
 6 | //     对此文件的更改可能导致不正确的行为,如果
 7 | //     重新生成代码,则所做更改将丢失。
 8 | // 
 9 | //------------------------------------------------------------------------------
10 | 
11 | namespace WpfApp.Properties
12 | {
13 | 
14 | 
15 |     /// 
16 |     ///   强类型资源类,用于查找本地化字符串等。
17 |     /// 
18 |     // 此类是由 StronglyTypedResourceBuilder
19 |     // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 |     // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 |     // (以 /str 作为命令选项),或重新生成 VS 项目。
22 |     [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 |     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 |     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 |     internal class Resources
26 |     {
27 | 
28 |         private static global::System.Resources.ResourceManager resourceMan;
29 | 
30 |         private static global::System.Globalization.CultureInfo resourceCulture;
31 | 
32 |         [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 |         internal Resources()
34 |         {
35 |         }
36 | 
37 |         /// 
38 |         ///   返回此类使用的缓存 ResourceManager 实例。
39 |         /// 
40 |         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 |         internal static global::System.Resources.ResourceManager ResourceManager
42 |         {
43 |             get
44 |             {
45 |                 if ((resourceMan == null))
46 |                 {
47 |                     global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WpfApp.Properties.Resources", typeof(Resources).Assembly);
48 |                     resourceMan = temp;
49 |                 }
50 |                 return resourceMan;
51 |             }
52 |         }
53 | 
54 |         /// 
55 |         ///   覆盖当前线程的 CurrentUICulture 属性
56 |         ///   使用此强类型的资源类的资源查找。
57 |         /// 
58 |         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 |         internal static global::System.Globalization.CultureInfo Culture
60 |         {
61 |             get
62 |             {
63 |                 return resourceCulture;
64 |             }
65 |             set
66 |             {
67 |                 resourceCulture = value;
68 |             }
69 |         }
70 |     }
71 | }
72 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/Properties/Resources.resx:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
 62 |   
 63 |     
 64 |       
 65 |         
 66 |           
 67 |             
 68 |               
 69 |                 
 70 |               
 71 |               
 72 |               
 73 |               
 74 |             
 75 |           
 76 |           
 77 |             
 78 |               
 79 |               
 80 |             
 81 |           
 82 |           
 83 |             
 84 |               
 85 |                 
 86 |                 
 87 |               
 88 |               
 89 |               
 90 |               
 91 |             
 92 |           
 93 |           
 94 |             
 95 |               
 96 |                 
 97 |               
 98 |               
 99 |             
100 |           
101 |         
102 |       
103 |     
104 |   
105 |   
106 |     text/microsoft-resx
107 |   
108 |   
109 |     2.0
110 |   
111 |   
112 |     System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |   
114 |   
115 |     System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |   
117 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
 1 | //------------------------------------------------------------------------------
 2 | // 
 3 | //     This code was generated by a tool.
 4 | //     Runtime Version:4.0.30319.42000
 5 | //
 6 | //     Changes to this file may cause incorrect behavior and will be lost if
 7 | //     the code is regenerated.
 8 | // 
 9 | //------------------------------------------------------------------------------
10 | 
11 | namespace WpfApp.Properties
12 | {
13 | 
14 | 
15 |     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 |     [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 |     internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 |     {
19 | 
20 |         private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 | 
22 |         public static Settings Default
23 |         {
24 |             get
25 |             {
26 |                 return defaultInstance;
27 |             }
28 |         }
29 |     }
30 | }
31 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |   
4 |     
5 |   
6 |   
7 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/SourceProject/.gitignore:
--------------------------------------------------------------------------------
1 | *.Source.SourceProject.props
--------------------------------------------------------------------------------
/sample/WPF/WpfApp/WpfApp.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 |   
 3 |   
 4 |     $(MSBuildToolsPath)\Microsoft.CSharp.targets
 5 |     net45;
 6 |     WinExe
 7 |     WpfApp
 8 |     WpfApp
 9 |   
10 |  
11 |   
12 |     
13 |       %(Filename)
14 |     
15 |     
16 |       Designer
17 |       MSBuild:Compile
18 |     
19 | 
20 |     
21 |     
22 |     
23 |     
24 |     
25 |     
26 |     
27 |   
28 |  
29 |   
30 |     
31 |   
32 |  
33 |   
34 |     
35 |     
36 |     
37 |     
38 |     
39 |     
40 |     
41 |     
42 |     
43 |     
44 |     
45 |     
46 |   
47 |   
48 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfUI/InterestingControl.xaml:
--------------------------------------------------------------------------------
 1 | 
 7 |     
 8 |         
 9 |             
10 |             
11 |         
12 |     
13 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfUI/InterestingControl.xaml.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Linq;
 4 | using System.Text;
 5 | using System.Threading.Tasks;
 6 | using System.Windows;
 7 | using System.Windows.Controls;
 8 | using System.Windows.Data;
 9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 | 
16 | namespace WpfUI
17 | {
18 |     /// 
19 |     /// InterestingControl.xaml 的交互逻辑
20 |     /// 
21 |     public partial class InterestingControl : UserControl
22 |     {
23 |         public InterestingControl()
24 |         {
25 |             InitializeComponent();
26 |         }
27 | 
28 |         private void Button_OnClick(object sender, RoutedEventArgs e)
29 |         {
30 |             TextBlock.Text = "Hello world";
31 |         }
32 |     }
33 | }
34 | 
--------------------------------------------------------------------------------
/sample/WPF/WpfUI/WpfUI.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 |   
 3 |     $(MSBuildToolsPath)\Microsoft.CSharp.targets
 4 |     net45;
 5 |     Library
 6 |     WpfUI
 7 |     WpfUI
 8 |     true
 9 |   
10 |   
11 |     $(DefineConstants);WPF
12 |   
13 |  
14 |   
15 |     
16 |       %(Filename)
17 |     
18 |     
19 |       Designer
20 |       MSBuild:Compile
21 |     
22 | 
23 |     
24 |     
25 |     
26 |     
27 |     
28 |     
29 |     
30 |   
31 |  
32 |   
33 |     
34 |     
35 |     
36 |     
37 |     
38 |   
39 |  
40 |   
41 |     
42 |       all
43 |       runtime; build; native; contentfiles; analyzers
44 |     
45 |   
46 |  
47 |   
48 |     
49 |     
50 |     
51 |     
52 |     
53 |     
54 |     
55 |     
56 |     
57 |     
58 |     
59 |     
60 |   
61 |  
62 |   
63 |     
64 |       Code
65 |     
66 |   
67 |  
68 |   
69 |     
70 |   
71 |  
72 |   
73 |     
74 |       MSBuild:Compile
75 |     
76 |   
77 | 
--------------------------------------------------------------------------------
/sample/build/Version.props:
--------------------------------------------------------------------------------
1 | 
2 |   
3 |     1.0.3-alpha06
4 |   
5 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Current/Core.targets:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
  4 |     $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
  5 |   
  6 | 
  7 |   
  8 |     
  9 |     
 10 |     <_SourceYardMultiTargetingPackageInfoFolder>$([System.IO.Path]::Combine($(BaseIntermediateOutputPath),$(Configuration),"SourceYardMultiTargetingPackageInfoFolder"))
 11 |    
 12 |     
 17 |   
 18 |   
 19 |   
 20 | 
 21 |   
 23 |     
 24 |     
 25 |       <_PackageReferenceVersion
 26 |           Include="Name='%(PackageReference.Identity)' Version='%(PackageReference.Version)' PrivateAssets='%(PackageReference.PrivateAssets)'">
 27 |       
 28 |     
 29 |   
 30 | 
 31 |   
 33 |     
 34 |       
 35 |       <_TfmSpecificFrameworkAssemblyReferences Include="@(ReferencePath->'%(OriginalItemSpec)')"
 36 |                                                Condition="'%(ReferencePath.Pack)' != 'false' AND '%(ReferencePath.ResolvedFrom)' == '{TargetFrameworkDirectory}'">
 37 |       
 38 |     
 39 |   
 40 | 
 41 |   
 42 |   
 43 |     
 44 |       
 45 |       <_SourceYardMultiTargetingPackageInfoFile>$([System.IO.Path]::Combine($(_SourceYardMultiTargetingPackageInfoFolder),"$(TargetFramework).txt"))
 46 | 
 47 |       
 48 |       
 49 |       $([System.IO.Path]::Combine($(BaseIntermediateOutputPath),$(IntermediateOutputPath),"SourcePacking"))
 50 | 
 51 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"CompileFile.txt"))
 52 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"ResourceFile.txt"))
 53 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"ContentFile.txt"))
 54 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"NoneFile.txt"))
 55 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"EmbeddedResourceFile.txt"))
 56 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"PageFile.txt"))
 57 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"ApplicationDefinitionFile.txt"))
 58 | 
 59 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"DescriptionFile.txt"))
 60 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"CopyrightFile.txt"))
 61 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"PackageReleaseNotesFile.txt"))
 62 | 
 63 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"PackageReferenceVersionFile.txt"))
 64 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"FrameworkReferenceVersionFile.txt"))
 65 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceProjectPackageFile.txt"))
 66 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardPackageReferenceFile.txt"))
 67 | 
 68 |       
 69 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardExcludePackageReferenceFile.txt"))
 70 |       
 71 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardExcludeFileItemFile.txt"))
 72 | 
 73 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardCompilePackageFile.txt"))
 74 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardResourcePackageFile.txt"))
 75 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardContentPackageFile.txt"))
 76 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardNonePackageFile.txt"))
 77 |       $([System.IO.Path]::Combine($(SourcePackingDirectory),"SourceYardEmbeddedResourcePackageFile.txt"))
 78 |     
 79 | 
 80 |     
 81 |       
 82 |       
 83 |       
 84 |       
 85 |       
 86 |       
 87 |       
 88 |       <_SourceYardCompilePackage Include="%(SourceYardCompile.Identity)|%(SourceYardCompile.SourcePackagePath)"/>
 89 |       <_SourceYardResourcePackage Include="%(SourceYardResource.Identity)|%(SourceYardResource.SourcePackagePath)"/>
 90 |       <_SourceYardContentPackage Include="%(SourceYardContent.Identity)|%(SourceYardContent.SourcePackagePath)"/>
 91 |       <_SourceYardNonePackage Include="%(SourceYardNone.Identity)|%(SourceYardNone.SourcePackagePath)"/>
 92 |       <_SourceYardEmbeddedResourcePackage Include="%(SourceYardEmbeddedResource.Identity)|%(SourceYardEmbeddedResource.SourcePackagePath)"/>
 93 | 
 94 |       
 95 |       
 96 |       <_SourceYardForSourceFusionCompilePackage Include="%(_SourceFusionIncludedCompileFile.Identity)|%(_SourceFusionIncludedCompileFile.Identity)"/>
 97 |     
 98 | 
 99 |     
100 | 
101 |       --Authors "$(Authors)"
102 | 
103 |       
107 |       --PackageLicenseUrl "$(PackageLicenseUrl)"
108 | 
109 |       --CopyrightFile "$(CopyrightFile)"
110 | 
111 |       -v $(PackageVersion)
112 | 
113 |       --DescriptionFile "$(DescriptionFile)"
114 | 
115 |       --Title "$(Title)"
116 |       --Owner "$(Owner)"
117 |       --PackageTags "$(PackageTags)"
118 |        --PackageReleaseNotesFile $(PackageReleaseNotesFile)
119 |       --PackageId "$(PackageId)"
120 | 
121 |       -p "$(MSBuildProjectFullPath)"
122 |      
123 |       -n "$(PackageOutputPath) "
124 |       -n "$(OutputPath) "
125 | 
126 |     
127 | 
128 |     
129 | 
130 |   
131 |   
132 |   
133 |   
134 |     
135 |     
136 | 
137 |     
138 | 
139 |     
140 |     
141 |     
142 | 
143 |     
144 |     
145 |     
146 |     
147 |     
148 |     
149 |     
150 | 
151 |     
152 |     
153 |     
154 | 
155 |     
156 |     
157 |     
158 |     
159 |     
160 |     
161 |     
162 | 
163 |     
164 |     
165 |     
166 | 
167 |     
168 |     
169 |     
170 |     
171 |     
174 |     
175 |     
178 | 
179 |     
180 |     
181 |     
182 |     
183 | 
184 |     
185 |   
186 |   
187 |   
188 |   
189 |  
190 |     
191 |     
192 | 
193 |     
194 |       
195 |       
197 |       
198 |       $(MSBuildThisFileDirectory)..\tools\net45\dotnetCampus.SourceYard.exe
199 |       dotnet $(MSBuildThisFileDirectory)../tools/netcoreapp2.0/dotnetCampus.SourceYard.dll
200 |     
201 | 
202 |     
204 |     
205 | 
206 |     
207 |   
208 | 
209 |   
210 |     $(CleanDependsOn);_SourceYardClean
211 |   
212 | 
213 |   
214 |     
215 |       <_SourcePackingDirectory>$([System.IO.Path]::Combine($(IntermediateOutputPath),"SourcePacking"))
216 |     
217 |     
218 |   
219 | 
220 |   
222 |     
223 |   
224 | 
225 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Current/build/PackageId.props:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |   
4 |     $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 |   
6 | 
7 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Current/build/PackageId.targets:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
 5 |   
 6 | 
 7 |   
 8 |   
 9 |   
10 |   
11 | 
12 |   
13 |   
15 |     
16 |     
17 |     
18 |     
19 |     
20 |     
21 |   
22 |   
23 |   
24 |   
26 |     
27 |     
28 |     
29 |     
30 |   
31 | 
32 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Current/buildMultiTargeting/PackageId.props:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |   
4 |     $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
5 |   
6 | 
7 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Current/buildMultiTargeting/PackageId.targets:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 | 
 5 |   
 7 |     
 8 |     
 9 |     
10 |     
11 |   
12 | 
13 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/README.md:
--------------------------------------------------------------------------------
1 | # About the Folder Structure
2 | 
3 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/README.zh-cn.md:
--------------------------------------------------------------------------------
 1 | # 此文件夹结构
 2 | 
 3 | 此 Assets 目录有两个独立的文件夹,`Current` 和 `Target`。
 4 | 
 5 | - `Current`
 6 |     - 组织 dotnetCampus.SourceYard 的 NuGet 目录结构。
 7 |     - 此文件夹中的所有内容将会原封不动地打包到 dotnetCampus.SourceYard 的 NuGet 包中。
 8 | - `Target`
 9 |     - 组织安装此 NuGet 包的目标项目的 NuGet 目录结构。
10 |     - 例如,Foo 项目安装了此 dotnetCampus.SourceYard 包;那么,当 Foo 项目打包时,此文件夹中的内容将打包到 Foo 的 NuGet 包中。
11 |     - 此文件夹中的所有内容可以包含目标包的占位符,为了与 MSBuild 原生的占位符前缀 `$`, `@`, `%` 区分,此包使用 `#` 作为占位符前缀。
12 | 
13 | 对于以上每一个 NuGet 目录,都遵循通用的 NuGet 包的文件夹结构:
14 | 
15 | + `/`
16 |     - 根目录,用来放 readme.txt 的(已经有人提 issue 要求加入 markdown 支持了)
17 | + `lib/`
18 |     - 用来放引用程序集 .dll,文档注释 .xml 和符号文件 .pdb 的
19 | + `runtimes/`
20 |     - 用来放那些与平台相关的 .dll/.pdb/.pri 的
21 | + `content/`
22 |     - 任意种类的文件,在这个文件夹中的文件会在编译时拷贝到输出目录(保持文件夹结构)
23 | + `build/`
24 |     - 这里放 .props 和 .targets 文件,会自动被 NuGet 导入,成为项目的一部分(要求文件名与包名相同)
25 | + `buildCrossTargeting/`
26 |     - 这里也是放 .props 和 .targets 文件,会自动被 NuGet 导入,成为项目的一部分(要求文件名与包名相同)
27 | + `tools/`
28 |     - PowerShell 脚本或者程序,在这里的工具可以在“包管理控制台”(Package Manager Console) 中使用
29 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Target/build/$(PackageId).SourceProject.props:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |   
 5 |   
 6 | 
 7 |   
 8 |   
 9 |     
10 |   
13 |   
14 |   
15 |   
16 |     
19 | 
20 | 
21 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Target/build/$(PackageId).props:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 4 |         
 5 |     
 6 | 
 7 |     
 8 |         
12 |         True
13 | 
14 |         
15 |         False
16 |     
17 | 
18 |     
19 |         
20 |         $(SourceYardPackageReference);#(PackageId)
21 |     
22 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Assets/Target/build/$(PackageId).targets:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
  4 |     
  5 |     
  6 |     
  7 |       all
  8 |       all
  9 |     
 10 |   
 11 | 
 12 |   
 13 |     <_#(PackageGuid)ImportInWpfTempProjectDependsOn>
 14 |       _#(PackageGuid)IncludeSourceCodes
 15 |     
 16 | 
 17 |     <_#(PackageGuid)ImportInWpfXamlDependsOn>
 18 |       _#(PackageGuid)XamlItemGroupIncludeSourceCodes
 19 |     
 20 |   
 21 | 
 22 |   
 23 |     <_#(PackageGuid)ImportInWpfTempProjectDependsOn>
 24 |       _#(PackageGuid)IncludeSOURCE_REFERENCESourceCodes
 25 |     
 26 | 
 27 |     <_#(PackageGuid)ImportInWpfXamlDependsOn>
 28 |       _#(PackageGuid)IncludeXamlItemGroupSOURCE_REFERENCESourceCodes
 29 |     
 30 |   
 31 | 
 32 |   
 33 | 
 34 |   
 35 |     $(DefineConstants);SOURCE_REFERENCE
 36 |   
 37 | 
 38 |   
 39 |     
 40 |   
 41 | 
 42 |   
 44 |     
 45 |     
 46 |   
 47 | 
 48 |   
 50 |     
 51 |     
 52 |   
 53 | 
 54 |   
 56 |     
 57 |     
 58 |   
 59 | 
 60 |   
 62 |     
 63 |     
 64 |   
 65 | 
 66 |   
 68 |     
 69 |     
 70 |   
 71 | 
 72 |   
 74 |     
 75 |     
 76 | 
 77 |   
 78 | 
 79 | 
 80 | 
 81 |   
 85 | 
 86 |   
 91 |     
 92 |       <_GeneratedCodeFiles Include="@(_#(PackageGuid)Compile)" />
 93 |     
 94 |   
 95 | 
 96 |   
 97 |   
 99 |     
100 |       
101 |     
102 |   
103 | 
104 |   
107 |     
108 |       
109 |       
110 |     
111 |     
112 |   
113 | 
114 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Cli/Options.cs:
--------------------------------------------------------------------------------
  1 | using dotnetCampus.Cli;
  2 | 
  3 | namespace dotnetCampus.SourceYard.Cli
  4 | {
  5 |     internal class Options
  6 |     {
  7 |         /// 
  8 |         /// 项目文件所在的路径
  9 |         /// 
 10 |         [Option('p', "Project", Description = "The full path of the project file.")]
 11 |         public string ProjectFile { get; set; } = null!;
 12 | 
 13 |         ///// 
 14 |         ///// 临时的文件夹的路径
 15 |         ///// 
 16 |         //[Option('i', "intermediate-directory", Description = "The relative path of the project intermediate output path, commonly the 'obj' folder and value in 'obj'.")]
 17 |         //public string IntermediateDirectory { get; set; } = null!;
 18 | 
 19 |         /// 
 20 |         /// 打包输出的文件夹
 21 |         /// 
 22 |         [Option('n', "PackageOutputPath", Description = "The package output full path of the project.")]
 23 |         public string PackageOutputPath { get; set; } = null!;
 24 | 
 25 |         /// 
 26 |         /// 当前项目的打包版本
 27 |         /// 
 28 |         [Option('v', "PackageVersion",
 29 |             // 默认不需要加上打包版本
 30 |             Description = "The package version value.")]
 31 |         public string PackageVersion { get; set; } = "1.0.0";
 32 | 
 33 |         ///// 
 34 |         ///// 项目进行编译的文件的列表,因为参数太多,需要将参数写到文件
 35 |         ///// 
 36 |         //[Option(longName: "Compile", Description = "编译的文件")]
 37 |         //public string? CompileFile { get; set; }
 38 | 
 39 |         ///// 
 40 |         ///// 存放资源文件参数的文件
 41 |         ///// 
 42 |         //[Option(longName: "Resource", Description = "资源文件")]
 43 |         //public string? ResourceFile { get; set; }
 44 | 
 45 |         //[Option(longName: "Content")]
 46 |         //public string? ContentFile { get; set; }
 47 | 
 48 |         //[Option(longName: "Page")]
 49 |         //public string? Page { get; set; }
 50 | 
 51 |         //[Option(longName: "None")]
 52 |         //public string? None { get; set; }
 53 | 
 54 |         //[Option(longName: "EmbeddedResource")]
 55 |         //public string? EmbeddedResource { get; set; }
 56 | 
 57 |         /// 
 58 |         /// 打包的公司内容
 59 |         /// 
 60 |         [Option(longName: "Company")]
 61 |         public string? Company { get; set; }
 62 | 
 63 |         [Option(longName: "Authors")]
 64 |         public string? Authors { get; set; }
 65 | 
 66 |         // 内容放在 SourceProjectPackageFile 文件
 67 |         //[Option(longName: "RepositoryUrl")]
 68 |         //public string RepositoryUrl { get; set; }
 69 | 
 70 |         //[Option(longName: "RepositoryType")]
 71 |         //public string RepositoryType { get; set; }
 72 | 
 73 |         //[Option(longName: "PackageProjectUrl")]
 74 |         //public string PackageProjectUrl { get; set; }
 75 | 
 76 |         /// 
 77 |         /// 因为 Copyright 可能很长,有空格,写文件
 78 |         /// 
 79 |         [Option(longName: "CopyrightFile")]
 80 |         public string? CopyrightFile { get; set; }
 81 | 
 82 |         [Option(longName: "DescriptionFile")]
 83 |         public string? DescriptionFile { get; set; }
 84 | 
 85 |         //[Option(longName: "ApplicationDefinition")]
 86 |         //public string? ApplicationDefinition { get; set; }
 87 | 
 88 |         [Option(longName: "Owner")]
 89 |         public string? Owner { get; set; }
 90 | 
 91 |         [Option(longName: "Title")]
 92 |         public string? Title { get; set; }
 93 | 
 94 |         [Option(longName: "PackageLicenseUrl")]
 95 |         public string? PackageLicenseUrl { get; set; }
 96 | 
 97 |         [Option(longName: "PackageIconUrl")]
 98 |         public string? PackageIconUrl { get; set; }
 99 | 
100 |         [Option(longName: "PackageReleaseNotesFile")]
101 |         public string? PackageReleaseNotesFile { get; set; }
102 | 
103 |         [Option(longName: "PackageTags")]
104 |         public string? PackageTags { get; set; }
105 | 
106 |         [Option(longName: "PackageId")] 
107 |         public string? PackageId { get; set; }
108 | 
109 |         //[Option(longName: "PackageReferenceVersion")]
110 |         //public string? PackageReferenceVersion { get; set; }
111 | 
112 |         ///// 
113 |         ///// 打包用到的文件夹
114 |         ///// 
115 |         //[Option(longName: "SourcePackingDirectory")]
116 |         //public string SourcePackingDirectory { get; set; } = null!;
117 | 
118 |         [Option(longName: "TargetFramework")]
119 |         public string? TargetFramework { get; set; }
120 | 
121 |         [Option(longName: "TargetFrameworks")]
122 |         public string? TargetFrameworks { get; set; }
123 | 
124 |         /// 
125 |         /// 多框架信息存放的文件夹,即使是单框架项目也会存在此文件夹
126 |         /// 
127 |         [Option("MultiTargetingPackageInfoFolder")]
128 |         public string MultiTargetingPackageInfoFolder { set; get; } = null!;
129 |     }
130 | }
131 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/IPackingContext.cs:
--------------------------------------------------------------------------------
 1 | using dotnetCampus.SourceYard.Utils;
 2 | 
 3 | namespace dotnetCampus.SourceYard.Context
 4 | {
 5 |     /// 
 6 |     /// 包含对项目进行源码打包所需的上下文信息。
 7 |     /// 
 8 |     internal interface IPackingContext
 9 |     {
10 |         /// 
11 |         /// 使用  在编译过程记录日志,其中的错误和警告将带来编译错误和编译警告。
12 |         /// 
13 |         ILogger Logger { get; }
14 | 
15 |         /// 
16 |         /// 需要进行源码打包的项目文件。
17 |         /// 
18 |         string ProjectFile { get; }
19 | 
20 |         /// 
21 |         /// 需要进行源码打包的项目所在的文件夹。
22 |         /// 
23 |         string ProjectFolder { get; }
24 | 
25 |         /// 
26 |         /// 需要进行源码打包的项目的项目名称。
27 |         /// 
28 |         string ProjectName { get; }
29 | 
30 |         /// 
31 |         /// 需要进行源码打包的项目的包 Id。
32 |         /// 
33 |         string PackageId { get; }
34 | 
35 |         /// 
36 |         /// 需要进行源码打包的项目的全局唯一标识符。
37 |         /// 
38 |         string PackageGuid { get; set; }
39 | 
40 |         /// 
41 |         /// 源码包的包版本。
42 |         /// 
43 |         string PackageVersion { get; }
44 | 
45 |         /// 
46 |         /// 源码包(nupkg)文件应该输出到此路径所在的文件夹下。
47 |         /// 
48 |         string PackageOutputPath { get; }
49 | 
50 |         /// 
51 |         /// 为了打源码包可以使用的打包临时文件夹。NuGet 包会按照此文件夹的文件夹结构来生成 nupkg 文件。
52 |         /// 
53 |         string PackingFolder { get; }
54 | 
55 |         /// 
56 |         /// 要打包项目的元素
57 |         /// 
58 |         PackagedProjectFile PackagedProjectFile { get; }
59 | 
60 |         BuildProps BuildProps { get; }
61 | 
62 |         /// 
63 |         /// 多框架的打包内容
64 |         /// 
65 |         /// 路径是 obj\Debug\SourceYardMultiTargetingPackageInfoFolder
66 |         /// 内容如下
67 |         /// - obj\Debug\SourceYardMultiTargetingPackageInfoFolder\net45.txt
68 |         /// - obj\Debug\SourceYardMultiTargetingPackageInfoFolder\net5.0.txt
69 |         MultiTargetingPackageInfo MultiTargetingPackageInfo { get; }
70 |     }
71 | }
72 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/MultiTargetingPackageInfo.cs:
--------------------------------------------------------------------------------
 1 | using System.Collections.Generic;
 2 | using System.IO;
 3 | using System.Linq;
 4 | using dotnetCampus.SourceYard.Cli;
 5 | 
 6 | namespace dotnetCampus.SourceYard.Context
 7 | {
 8 |     class MultiTargetingPackageInfo
 9 |     {
10 |         public MultiTargetingPackageInfo(Options options)
11 |             : this(new DirectoryInfo(options.MultiTargetingPackageInfoFolder), options.TargetFrameworks)
12 |         {
13 |         }
14 | 
15 |         public MultiTargetingPackageInfo(DirectoryInfo multiTargetingPackageInfoFolder, string? targetFrameworks)
16 |         {
17 |             MultiTargetingPackageInfoFolder = multiTargetingPackageInfoFolder;
18 |             var folder = multiTargetingPackageInfoFolder.FullName;
19 |             var targetFrameworkPackageInfoList = new List();
20 | 
21 |             foreach (var file in Directory.GetFiles(folder, "*.txt"))
22 |             {
23 |                 var packageInfo = File.ReadAllText(file!);
24 |                 var sourcePackingFolder = packageInfo.Trim('\r', '\n');
25 |                 sourcePackingFolder = Path.GetFullPath(sourcePackingFolder);
26 | 
27 |                 // 判断此文件是否合法
28 |                 // 判断方法如获取 CompileFile.txt 是否存在
29 |                 var compileFile = Path.Combine(sourcePackingFolder, "CompileFile.txt");
30 |                 if (File.Exists(compileFile))
31 |                 {
32 |                     var targetFramework = Path.GetFileNameWithoutExtension(file);
33 |                     targetFrameworkPackageInfoList.Add(new TargetFrameworkPackageInfo(targetFramework,
34 |                         new DirectoryInfo(sourcePackingFolder)));
35 |                 }
36 |             }
37 | 
38 |             TargetFrameworkPackageInfoList = targetFrameworkPackageInfoList;
39 | 
40 |             var validTargetFrameworkPackageInfoList = targetFrameworkPackageInfoList.ToList();
41 |             validTargetFrameworkPackageInfoList.RemoveAll(t =>
42 |             {
43 |                 if (t.IsValid is false)
44 |                 {
45 |                     return true;
46 |                 }
47 | 
48 |                 if (targetFrameworks != null && !string.IsNullOrWhiteSpace(targetFrameworks))
49 |                 {
50 |                     // 对于单框架,也许 targetFrameworks 的值是空字符串
51 |                     if (!targetFrameworks.Contains(t.TargetFramework))
52 |                     {
53 |                         // 例外项是什么?如 TargetFrameworks 包含 4.5.1 版本,但是 TargetFramework 是 4.5 版本,此时判断是对的
54 |                         // 但是这里其实不需要精确判断,有 4.5.1 版本,自然就支持 4.5 和以下
55 | 
56 |                         // 是否让 TargetFramework 存放空字符串?也许,但是过不了 t.IsValid 的值
57 |                         return true;
58 |                     }
59 |                 }
60 | 
61 |                 return false;
62 |             });
63 | 
64 |             ValidTargetFrameworkPackageInfoList = validTargetFrameworkPackageInfoList;
65 |         }
66 | 
67 | 
68 |         public DirectoryInfo MultiTargetingPackageInfoFolder { get; }
69 | 
70 |         public IReadOnlyList ValidTargetFrameworkPackageInfoList { get; }
71 |         public IReadOnlyList TargetFrameworkPackageInfoList { get; }
72 |     }
73 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/PackagedProjectFile.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.IO;
  4 | using System.Linq;
  5 | using dotnetCampus.SourceYard.Utils;
  6 | 
  7 | namespace dotnetCampus.SourceYard.Context
  8 | {
  9 |     /// 
 10 |     /// 被打包项目的文件,包括编译的文件资源文件
 11 |     /// 
 12 |     class PackagedProjectFile
 13 |     {
 14 |         public PackagedProjectFile(DirectoryInfo commonSourcePackingFolder, string projectFolder,
 15 |             BuildProps buildProps)
 16 |         {
 17 |             // 通过 commonSourcePackingFolder 可以拿到对应的输出文件路径
 18 |             string compileFile = GetFile("CompileFile.txt");
 19 |             string resourceFile = GetFile("ResourceFile.txt");
 20 |             string contentFile = GetFile("ContentFile.txt");
 21 |             string page = GetFile("PageFile.txt");
 22 |             string applicationDefinition = GetFile("ApplicationDefinitionFile.txt");
 23 |             string noneFile = GetFile("NoneFile.txt");
 24 |             string embeddedResource = GetFile("EmbeddedResourceFile.txt");
 25 | 
 26 |             _projectFolder = projectFolder;
 27 |             _buildProps = buildProps;
 28 |             ApplicationDefinition = applicationDefinition;
 29 | 
 30 |             CompileFileList = GetSourceYardPackageFileList(compileFile, SourceYardCompilePackageFile);
 31 |             ResourceFileList = GetSourceYardPackageFileList(resourceFile, SourceYardResourcePackageFile);
 32 |             ContentFileList = GetSourceYardPackageFileList(contentFile, SourceYardContentPackageFile);
 33 |             PageList = GetFileList(page);
 34 |             NoneFileList = GetSourceYardPackageFileList(noneFile, SourceYardNonePackageFile);
 35 |             EmbeddedResourceList = GetSourceYardPackageFileList(embeddedResource, SourceYardEmbeddedResourcePackageFile);
 36 | 
 37 |             string GetFile(string fileName)
 38 |             {
 39 |                 return Path.Combine(commonSourcePackingFolder.FullName, fileName);
 40 |             }
 41 |         }
 42 | 
 43 |         private const string
 44 |             SourceYardCompilePackageFile = "SourceYardCompilePackageFile.txt",
 45 |             SourceYardResourcePackageFile = "SourceYardResourcePackageFile.txt",
 46 |             SourceYardContentPackageFile = "SourceYardContentPackageFile.txt",
 47 |             SourceYardNonePackageFile = "SourceYardNonePackageFile.txt",
 48 |             SourceYardEmbeddedResourcePackageFile = "SourceYardEmbeddedResourcePackageFile.txt";
 49 | 
 50 |         /// 
 51 |         /// 需要做源码包的项目的编译的文件
 52 |         /// 
 53 |         public IReadOnlyList CompileFileList { get; }
 54 | 
 55 |         /// 
 56 |         /// 需要做源码包的项目的资源文件
 57 |         /// 
 58 |         public IReadOnlyList ResourceFileList { get; }
 59 | 
 60 |         /// 
 61 |         /// 需要做源码包项目的文件
 62 |         /// 
 63 |         public IReadOnlyList ContentFileList { get; }
 64 | 
 65 |         /// 
 66 |         /// 需要做源码包项目的页面
 67 |         /// 
 68 |         public IReadOnlyList PageList { get; }
 69 | 
 70 |         /// 
 71 |         /// 嵌入文件
 72 |         /// 
 73 |         public IReadOnlyList EmbeddedResourceList { get; }
 74 | 
 75 |         /// 
 76 |         /// 需要做源码包项目的文件
 77 |         /// 
 78 |         private string ApplicationDefinition { get; }
 79 | 
 80 |         public IReadOnlyList NoneFileList { get; }
 81 | 
 82 |         public IReadOnlyList GetAllFile()
 83 |         {
 84 |             return new CombineReadonlyList(CompileFileList, ResourceFileList, ContentFileList,
 85 |                 PageList,
 86 |                 NoneFileList, EmbeddedResourceList);
 87 |         }
 88 | 
 89 |         private List GetSourceYardPackageFileList(string file,
 90 |             string sourceYardPackageFile)
 91 |         {
 92 |             sourceYardPackageFile = Path.Combine(_buildProps.SourcePackingDirectory, sourceYardPackageFile);
 93 |             var sourceYardPackageFileList = ParseSourceYardPackageFile(sourceYardPackageFile);
 94 | 
 95 |             var fileList = GetFileList(file);
 96 |             return new CombineReadonlyList(sourceYardPackageFileList, fileList).Distinct(new SourceYardPackageFileEqualityComparer()).ToList();
 97 |         }
 98 | 
 99 |         private List ParseSourceYardPackageFile(string sourceYardPackageFile)
100 |         {
101 |             var sourceYardPackageFileList = new List();
102 |             var text = File.ReadAllText(sourceYardPackageFile);
103 | 
104 |             foreach (var line in text.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
105 |             {
106 |                 var package = line.Split('|');
107 |                 if (package.Length == 2)
108 |                 {
109 |                     var sourceFile = package[0];
110 |                     var packagePath = package[1];
111 | 
112 |                     if (!string.IsNullOrEmpty(sourceFile))
113 |                     {
114 |                         sourceYardPackageFileList.Add(new SourceYardPackageFile(new FileInfo(sourceFile), packagePath));
115 |                     }
116 |                 }
117 |             }
118 | 
119 |             return sourceYardPackageFileList;
120 |         }
121 | 
122 |         private List GetFileList(string file)
123 |         {
124 |             if (string.IsNullOrEmpty(file) || !File.Exists(file))
125 |             {
126 |                 return new List();
127 |             }
128 | 
129 |             var fileList = File.ReadAllLines(file).ToList();
130 | 
131 |             fileList = RemoveTempFile(fileList);
132 | 
133 |             for (var i = 0; i < fileList.Count; i++)
134 |             {
135 |                 var fullPath = Path.GetFullPath(fileList[i]);
136 | 
137 |                 // 如果文件放在项目文件上面,如 Foo\F1\F.csproj 引用文件 Foo\12.txt 那么此时就不添加 12.txt 的引用
138 |                 // 原因是将 F.csproj 所在文件夹放在源代码包的 src 文件夹里面,因此 F1 文件夹是最上层文件夹
139 |                 if (fullPath.IndexOf(_projectFolder, StringComparison.OrdinalIgnoreCase) < 0)
140 |                 {
141 |                     fileList.RemoveAt(i);
142 |                     i--;
143 |                 }
144 |             }
145 | 
146 |             return fileList.Select(temp => new SourceYardPackageFile(new FileInfo(temp), temp)).ToList();
147 |         }
148 | 
149 |         private List RemoveTempFile(List fileList)
150 |         {
151 |             fileList.RemoveAll
152 |             (
153 |                 temp => IgnoreFolderList.Any(t => temp.StartsWith(t, StringComparison.OrdinalIgnoreCase))
154 |             );
155 | 
156 |             fileList.RemoveAll(temp =>
157 |             {
158 |                 var pathRoot = Path.GetPathRoot(temp);
159 |                 if (!string.IsNullOrEmpty(pathRoot))
160 |                 {
161 |                     return temp.StartsWith(pathRoot, StringComparison.OrdinalIgnoreCase);
162 |                 }
163 | 
164 |                 return false;
165 |             });
166 | 
167 |             fileList.RemoveAll(temp =>
168 |                 IgnoreFileEndList.Any(t => temp.EndsWith(t, StringComparison.OrdinalIgnoreCase)));
169 | 
170 |             // 忽略被排除的文件
171 |             fileList.RemoveAll(temp =>
172 |                 _buildProps.SourceYardExcludeFileItemList.Contains(temp, StringComparer.OrdinalIgnoreCase));
173 | 
174 |             return fileList;
175 |         }
176 | 
177 |         /// 
178 |         /// 项目文件夹
179 |         /// 
180 |         private readonly string _projectFolder;
181 | 
182 |         private readonly BuildProps _buildProps;
183 | 
184 |         /// 
185 |         /// 忽略的文件夹列表
186 |         /// 
187 |         private static IList IgnoreFolderList { get; } = new List()
188 |         {
189 |             ".vs", "bin", "obj", ".git", "x64", "x86"
190 |         };
191 | 
192 |         /// 
193 |         /// 忽略的文件后缀列表
194 |         /// 
195 |         private static IList IgnoreFileEndList { get; } = new List()
196 |         {
197 |             ".csproj.DotSettings", ".suo", ".user", ".sln.docstates",
198 |             ".nupkg",
199 |             // 忽略原因请看 https://github.com/dotnet-campus/SourceYard/issues/98
200 |             "launchSettings.json"
201 |         };
202 | 
203 |         class SourceYardPackageFileEqualityComparer : IEqualityComparer
204 |         {
205 |             public bool Equals(SourceYardPackageFile x, SourceYardPackageFile y)
206 |             {
207 |                 return x.SourceFile.FullName.Equals(y.SourceFile.FullName);
208 |             }
209 | 
210 |             public int GetHashCode(SourceYardPackageFile obj)
211 |             {
212 |                 return obj.SourceFile.FullName.GetHashCode();
213 |             }
214 |         }
215 |     }
216 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/PackingContext.cs:
--------------------------------------------------------------------------------
 1 | using System.IO;
 2 | using dotnetCampus.SourceYard.Utils;
 3 | 
 4 | namespace dotnetCampus.SourceYard.Context
 5 | {
 6 |     /// 
 7 |     internal class PackingContext : IPackingContext
 8 |     {
 9 |         public PackingContext(ILogger logger, string projectFile,
10 |             string projectName, string? packageId, string packageVersion, string packageOutputPath, string packingFolder,
11 |             PackagedProjectFile packagedProjectFile, MultiTargetingPackageInfo multiTargetingPackageInfo)
12 |         {
13 |             Logger = logger;
14 |           
15 |             ProjectFile = projectFile;
16 |             ProjectFolder = Path.GetDirectoryName(projectFile)!;
17 |             ProjectName = projectName;
18 |             packageId = packageId?.Trim() ?? "";
19 |             if (string.IsNullOrEmpty(packageId))
20 |             {
21 |                 PackageId = projectName + ".Source";
22 |             }
23 |             else
24 |             {
25 |                 PackageId = packageId + ".Source";
26 |             }
27 | 
28 |             PackageGuid = projectName.Replace(".", "");
29 |             PackingFolder = packingFolder;
30 |             PackagedProjectFile = packagedProjectFile;
31 |             MultiTargetingPackageInfo = multiTargetingPackageInfo;
32 |             PackageVersion = packageVersion;
33 |             PackageOutputPath = packageOutputPath;
34 |         }
35 | 
36 |         /// 
37 |         public ILogger Logger { get; }
38 | 
39 |         /// 
40 |         public string ProjectFile { get; }
41 | 
42 |         /// 
43 |         public string ProjectFolder { get; }
44 | 
45 |         /// 
46 |         public string ProjectName { get; }
47 | 
48 |         /// 
49 |         public string PackageId { get; }
50 | 
51 |         /// 
52 |         public string PackageGuid { get; set; }
53 | 
54 |         /// 
55 |         public string PackageVersion { get; }
56 | 
57 |         /// 
58 |         public string PackageOutputPath { get; }
59 | 
60 |         /// 
61 |         public string PackingFolder { get; }
62 | 
63 |         public PackagedProjectFile PackagedProjectFile { get; }
64 |         public MultiTargetingPackageInfo MultiTargetingPackageInfo { get; }
65 |         public BuildProps BuildProps { get; set; } = null!;
66 |     }
67 | }
68 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/SourceYardPackageFile.cs:
--------------------------------------------------------------------------------
 1 | using System.IO;
 2 | 
 3 | namespace dotnetCampus.SourceYard.Context
 4 | {
 5 |     /// 
 6 |     /// 放在源代码包的文件
 7 |     /// 
 8 |     public class SourceYardPackageFile
 9 |     {
10 |         /// 
11 |         /// 创建放在源代码包的文件
12 |         /// 
13 |         /// 
14 |         /// 
15 |         public SourceYardPackageFile(FileInfo sourceFile, string sourcePackagePath)
16 |         {
17 |             SourceFile = sourceFile;
18 |             SourcePackagePath = sourcePackagePath;
19 |         }
20 | 
21 |         /// 
22 |         /// 源代码的文件
23 |         /// 
24 |         public FileInfo SourceFile { get; }
25 | 
26 |         /// 
27 |         /// 打包的路径
28 |         /// 
29 |         public string SourcePackagePath { get; }
30 |     }
31 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Context/TargetFrameworkPackageInfo.cs:
--------------------------------------------------------------------------------
 1 | using System.IO;
 2 | 
 3 | namespace dotnetCampus.SourceYard.Context
 4 | {
 5 |     class TargetFrameworkPackageInfo
 6 |     {
 7 |         public TargetFrameworkPackageInfo(string targetFramework, DirectoryInfo sourcePackingFolder)
 8 |         {
 9 |             TargetFramework = targetFramework;
10 |             SourcePackingFolder = sourcePackingFolder;
11 |         }
12 | 
13 |         public bool IsValid
14 |         {
15 |             get { return _isValid ??= GetIsValid(); }
16 |         }
17 | 
18 |         public string TargetFramework { get; }
19 |         public DirectoryInfo SourcePackingFolder { get; }
20 | 
21 |         private bool GetIsValid()
22 |         {
23 |             // 判断此文件是否合法
24 |             // 判断方法如获取 CompileFile.txt 是否存在
25 |             var compileFile = Path.Combine(SourcePackingFolder.FullName, "CompileFile.txt");
26 |             return File.Exists(compileFile);
27 |         }
28 | 
29 |         private bool? _isValid;
30 |     }
31 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Exception_/PackingException.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | 
 3 | namespace dotnetCampus.SourceYard
 4 | {
 5 |     internal class PackingException : Exception
 6 |     {
 7 |         public PackingException(string message,
 8 |             string? key = null,
 9 |             string? file = null) : base(message)
10 |         {
11 |             Key = key;
12 |             File = file;
13 |         }
14 | 
15 |         public string? Key { get; set; }
16 | 
17 |         public string? File { get; set; }
18 |     }
19 | }
20 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Logger_/ILogger.cs:
--------------------------------------------------------------------------------
 1 | using dotnetCampus.MSBuildUtils;
 2 | 
 3 | namespace dotnetCampus.SourceYard
 4 | {
 5 |     internal interface ILogger: IMSBuildLogger
 6 |     {
 7 |         void Warning(PackingException exception);
 8 | 
 9 |         void Error(PackingException exception);
10 |     }
11 | }
12 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Logger_/Logger.cs:
--------------------------------------------------------------------------------
 1 | using dotnetCampus.MSBuildUtils;
 2 | 
 3 | namespace dotnetCampus.SourceYard
 4 | {
 5 |     internal class Logger : MSBuildConsoleLogger, ILogger
 6 |     {
 7 |         public void Warning(PackingException exception)
 8 |         {
 9 |             var message = exception.Message;
10 |             if (!string.IsNullOrEmpty(exception.Key))
11 |             {
12 |                 message = exception.Key + ": " + exception.Message;
13 |             }
14 | 
15 |             Warning(message, targetFile:exception.File);
16 |         }
17 | 
18 |         public void Error(PackingException exception)
19 |         {
20 |             var message = exception.Message;
21 |             if (!string.IsNullOrEmpty(exception.Key))
22 |             {
23 |                 message = exception.Key + ": " + exception.Message;
24 |             }
25 | 
26 |             Error(message, targetFile: exception.File);
27 |         }
28 |     }
29 | }
30 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/AssetsPacker.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.IO;
 3 | using System.Text;
 4 | using dotnetCampus.SourceYard.Context;
 5 | using dotnetCampus.SourceYard.Utils;
 6 | 
 7 | namespace dotnetCampus.SourceYard.PackFlow
 8 | {
 9 |     internal class AssetsPacker : IPackFlow
10 |     {
11 |         public void Pack(IPackingContext context)
12 |         {
13 |             // 将 Assets 文件夹中的所有文件复制到打包文件夹中。
14 | 
15 |             var assetsFolder = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location) ?? throw new InvalidOperationException(), "Assets", "Target",
16 |                 "build");
17 | 
18 |             var copyFolder = Path.Combine(context.PackingFolder, "build");
19 |             FileSystem.CopyFolderContents(assetsFolder, copyFolder, name =>
20 |                 name.Replace("$(PackageId)", context.PackageId));
21 | 
22 |             // 替换 props 和 targets 文件中的占位符。
23 |             foreach (var file in new DirectoryInfo(copyFolder)
24 |                 .EnumerateFiles("*.*", SearchOption.AllDirectories))
25 |             {
26 |                 var builder = new StringBuilder(File.ReadAllText(file.FullName, Encoding.UTF8));
27 |                 builder
28 |                     .Replace("#(PackageId)", context.PackageId)
29 |                     .Replace("#(PackageGuid)", context.PackageGuid);
30 |                 File.WriteAllText(file.FullName, builder.ToString(), Encoding.UTF8);
31 |             }
32 |         }
33 |     }
34 | }
35 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/IPackFlow.cs:
--------------------------------------------------------------------------------
 1 | using dotnetCampus.SourceYard.Context;
 2 | 
 3 | namespace dotnetCampus.SourceYard.PackFlow
 4 | {
 5 |     internal interface IPackFlow
 6 |     {
 7 |         void Pack(IPackingContext context);
 8 |     }
 9 | }
10 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/ItemGroupPacker.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections.Generic;
 3 | using System.Diagnostics.Contracts;
 4 | using System.IO;
 5 | using System.Linq;
 6 | using System.Xml;
 7 | using System.Xml.Linq;
 8 | using System.Xml.XPath;
 9 | using dotnetCampus.SourceYard.Context;
10 | using dotnetCampus.SourceYard.Utils;
11 | 
12 | namespace dotnetCampus.SourceYard.PackFlow
13 | {
14 |     internal class ItemGroupPacker : IPackFlow
15 |     {
16 |         /// 
17 |         /// 获取应该被加入源码引用的项类型。
18 |         /// 
19 |         private static readonly string[] IncludingItemTypes =
20 |         {
21 |             // 由于需要多个项之间可能存在重合(用于 Update 和 Remove),所以 None 也是需要加入的。
22 |             "Compile", "Resource", "Content", "None"
23 |         };
24 | 
25 |         /// 
26 |         /// 获取应该被加入源码引用的 XAML 型的项类型。
27 |         /// 
28 |         private static readonly string[] XamlItemTypes =
29 |         {
30 |             // 由于需要多个项之间可能存在重合(用于 Update 和 Remove),所以 None 也是需要加入的。
31 |             "Page", "ApplicationDefinition"
32 |         };
33 | 
34 |         public void Pack(IPackingContext context)
35 |         {
36 |             var buildAssetsFile = Path.Combine(context.PackingFolder, "build", $"{context.PackageId}.targets");
37 | 
38 |             // 从原始的项目文件中提取所有的 ItemGroup 中的节点,且节点类型在 IncludingItemTypes 中。
39 | 
40 |             // nuget 的源代码
41 |             var sourceReferenceSourceFolder = @"$(MSBuildThisFileDirectory)..\src\";
42 | 
43 |             // 读取文件
44 |             var buildFile = File.ReadAllText(buildAssetsFile);
45 | 
46 |             buildFile = ReplaceString(context.PackagedProjectFile, buildFile, context.PackageGuid,
47 |                 sourceReferenceSourceFolder, false,
48 |                 "", "");
49 | 
50 |             // 本地的代码,用于调试本地的代码
51 | 
52 |             sourceReferenceSourceFolder = $@"$({context.PackageGuid}SourceFolder)\";
53 | 
54 |             buildFile = ReplaceString(context.PackagedProjectFile, buildFile, context.PackageGuid,
55 |                 sourceReferenceSourceFolder, true,
56 |                 "", "");
57 | 
58 |             // 用户可以选择使用 nuget 源代码,也可以选择使用自己的代码,所以就需要使用两个不同的值
59 | 
60 |             // 写入文件
61 |             File.WriteAllText(buildAssetsFile, buildFile);
62 |         }
63 | 
64 |         private string ReplaceString(PackagedProjectFile contextPackagedProjectFile, string str,
65 |             string packageGuid, string filePath, bool isVisible,
66 |             string replaceItemGroup, string replaceXmlItemGroup)
67 |         {
68 |             var groupElement =
69 |                 new ItemGroupElement(contextPackagedProjectFile, filePath, isVisible, packageGuid);
70 |             var (itemGroupElement, itemGroupElementOfXaml) = groupElement.GetItemGroup();
71 | 
72 |             return str.Replace(replaceItemGroup, itemGroupElement.ToString())
73 |                 .Replace(replaceXmlItemGroup, itemGroupElementOfXaml.ToString());
74 |         }
75 |     }
76 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuGetPacker.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.IO;
 3 | using System.IO.Compression;
 4 | using dotnetCampus.SourceYard.Context;
 5 | 
 6 | namespace dotnetCampus.SourceYard.PackFlow
 7 | {
 8 |     /// 
 9 |     /// 将文件压缩为 nuget 包
10 |     /// 
11 |     internal class NuGetPacker : IPackFlow
12 |     {
13 |         public void Pack(IPackingContext context)
14 |         {
15 |             var targetPackageFile = Path.GetFullPath(Path.Combine(context.PackageOutputPath,
16 |                 $"{context.PackageId}.{context.PackageVersion}.nupkg"));
17 |             if (File.Exists(targetPackageFile))
18 |             {
19 |                 context.Logger.Message($"发现{targetPackageFile}已经存在,将替换为新的文件");
20 |                 File.Delete(targetPackageFile);
21 |             }
22 | 
23 |             var directory = Path.GetDirectoryName(targetPackageFile);
24 |             if (directory == null)
25 |             {
26 |                 throw new NotSupportedException("不支持相对路径。");
27 |             }
28 | 
29 |             if (!Directory.Exists(directory))
30 |             {
31 |                 Directory.CreateDirectory(directory);
32 |             }
33 | 
34 |             // nuget 包就是一个 zip 压缩包
35 |             ZipFile.CreateFromDirectory(context.PackingFolder, targetPackageFile);
36 |         }
37 |     }
38 | }
39 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFileGenerator.cs:
--------------------------------------------------------------------------------
 1 | using System.IO;
 2 | using System.Xml.Serialization;
 3 | using dotnetCampus.SourceYard.Context;
 4 | using dotnetCampus.SourceYard.PackFlow.NuspecFiles;
 5 | using dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts;
 6 | 
 7 | namespace dotnetCampus.SourceYard.PackFlow
 8 | {
 9 |     /// 
10 |     /// 创建 Nuspec 文件
11 |     /// 
12 |     internal class NuspecFileGenerator : IPackFlow
13 |     {
14 |         public void Pack(IPackingContext context)
15 |         {
16 |             _log = context.Logger;
17 |             _log.Message("开始创建 nuspec 文件");
18 |             var nuspecPackage = GetNuspec(context);
19 | 
20 |             var fileName = $"{context.PackageId}.nuspec";
21 |             fileName = Path.Combine(context.PackingFolder, fileName);
22 | 
23 |             Write(nuspecPackage, fileName);
24 |             _log.Message("完成创建 nuspec 文件");
25 |         }
26 | 
27 |         private ILogger _log = null!;
28 | 
29 |         private void Write(NuspecPackage nuspecPackage, string fileName)
30 |         {
31 |             var file = new FileInfo(fileName);
32 |             var ns = new XmlSerializerNamespaces();
33 |             ns.Add("", "");
34 | 
35 |             //#if DEBUG
36 | 
37 |             //            var str = new StringBuilder();
38 |             //            using (var xmlWriter = XmlWriter.Create(str))
39 |             //            {
40 |             //                var xmlSerializer = new XmlSerializer(typeof(NuspecPackage));
41 |             //                xmlSerializer.Serialize(xmlWriter, nuspecPackage, ns);
42 |             //            }
43 | 
44 |             //            var rawceeyopereSuwhisa = str.ToString();
45 | 
46 |             //            rawceeyopereSuwhisa = rawceeyopereSuwhisa;
47 |             //#endif
48 | 
49 |             using (var stream = file.OpenWrite())
50 |             {
51 |                 var xmlSerializer = new XmlSerializer(typeof(NuspecPackage));
52 |                 xmlSerializer.Serialize(stream, nuspecPackage, ns);
53 |             }
54 |         }
55 | 
56 |         private NuspecPackage GetNuspec(IPackingContext context)
57 |         {
58 |             var buildProps = context.BuildProps;
59 | 
60 |             Repository? repository = null;
61 |             if (!string.IsNullOrEmpty(buildProps.RepositoryType) && !string.IsNullOrEmpty(buildProps.RepositoryUrl))
62 |             {
63 |                 repository = new Repository()
64 |                 {
65 |                     Type = buildProps.RepositoryType,
66 |                     Url = buildProps.RepositoryUrl
67 |                 };
68 |             }
69 | 
70 |             return new NuspecPackage()
71 |             {
72 |                 NuspecMetadata = new NuspecMetadata()
73 |                 {
74 |                     Authors = buildProps.Authors,
75 |                     Copyright = buildProps.Copyright,
76 |                     Description = buildProps.Description,
77 |                     PackageProjectUrl = buildProps.PackageProjectUrl,
78 |                     Version = context.PackageVersion,
79 |                     Id = context.PackageId,
80 |                     Owner = buildProps.Owner,
81 |                     Title = buildProps.Title,
82 |                     PackageIconUrl = buildProps.PackageIconUrl,
83 |                     PackageLicenseUrl = buildProps.PackageLicenseUrl,
84 |                     PackageTags = buildProps.PackageTags,
85 |                     PackageReleaseNotes = buildProps.PackageReleaseNotes,
86 |                     Dependencies = DependenciesParser.GetDependencies(context),
87 |                     FrameworkAssemblies = DependenciesParser.GetFrameworkAssemblies(context),
88 |                     Repository = repository
89 |                 }
90 |             };
91 |         }
92 |     }
93 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/DependenciesParser.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.IO;
  4 | using System.Linq;
  5 | using System.Text.RegularExpressions;
  6 | using dotnetCampus.SourceYard.Context;
  7 | using dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts;
  8 | 
  9 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles
 10 | {
 11 |     static class DependenciesParser
 12 |     {
 13 |         /// 
 14 |         /// 获取框架依赖内容
 15 |         /// 
 16 |         /// 
 17 |         /// 
 18 |         public static List? GetFrameworkAssemblies(IPackingContext context)
 19 |         {
 20 |             var nuspecFrameworkAssemblies = new List();
 21 | 
 22 |             foreach (var targetFrameworkPackageInfo in context.MultiTargetingPackageInfo
 23 |                 .ValidTargetFrameworkPackageInfoList)
 24 |             {
 25 |                 var sourcePackingFolder = targetFrameworkPackageInfo.SourcePackingFolder.FullName;
 26 | 
 27 |                 var frameworkReferenceVersionFile = Path.Combine(sourcePackingFolder, "FrameworkReferenceVersionFile.txt");
 28 | 
 29 |                 if (File.Exists(frameworkReferenceVersionFile))
 30 |                 {
 31 |                     foreach (var assembly in File.ReadAllLines(frameworkReferenceVersionFile).Where(t=>!string.IsNullOrWhiteSpace(t)))
 32 |                     {
 33 |                         nuspecFrameworkAssemblies.Add(new NuspecFrameworkAssembly()
 34 |                         {
 35 |                             TargetFramework = targetFrameworkPackageInfo.TargetFramework,
 36 |                             AssemblyName = assembly
 37 |                         });
 38 |                     }
 39 |                 }
 40 |             }
 41 | 
 42 |             if (nuspecFrameworkAssemblies.Count == 0)
 43 |             {
 44 |                 // 如果没有任何框架依赖,那么应该啥都不输出
 45 |                 return null;
 46 |             }
 47 | 
 48 |             return nuspecFrameworkAssemblies;
 49 |         }
 50 | 
 51 |         /// 
 52 |         /// 获取依赖内容
 53 |         /// 
 54 |         /// 
 55 |         public static List GetDependencies(IPackingContext context)
 56 |         {
 57 |             ILogger logger = context.Logger;
 58 |             var nuspecGroups = new List();
 59 | 
 60 |             foreach (var targetFrameworkPackageInfo in context.MultiTargetingPackageInfo.ValidTargetFrameworkPackageInfoList)
 61 |             {
 62 |                 var sourcePackingFolder = targetFrameworkPackageInfo.SourcePackingFolder.FullName;
 63 | 
 64 |                 var packageReferenceVersionFile = Path.Combine(sourcePackingFolder, "PackageReferenceVersionFile.txt");
 65 | 
 66 |                 var buildProps = context.BuildProps;
 67 |                 var dependencies = GetDependencies(packageReferenceVersionFile, buildProps.SourceYardPackageReferenceList,
 68 |                     buildProps.SourceYardExcludePackageReferenceList,logger);
 69 | 
 70 |                 nuspecGroups.Add(new NuspecGroup()
 71 |                 {
 72 |                     TargetFramework = targetFrameworkPackageInfo.TargetFramework,
 73 |                     Dependencies = dependencies
 74 |                 });
 75 |             }
 76 | 
 77 |             return nuspecGroups;
 78 |         }
 79 | 
 80 |         /// 
 81 |         /// 获取依赖
 82 |         /// 
 83 |         /// 引用的NuGet包于版本号
 84 |         /// 源代码包
 85 |         /// 排除的依赖
 86 |         /// 
 87 |         /// 
 88 |         private static List GetDependencies(string contextPackageVersion,
 89 |             List sourceYardPackageReferenceList, List excludePackageReferenceList, ILogger logger)
 90 |         {
 91 |             var nuspecDependencyList = ParserPackageVersion(contextPackageVersion, sourceYardPackageReferenceList, logger);
 92 | 
 93 |             // 如果在排除列表就移除
 94 |             if (excludePackageReferenceList.Count > 0)
 95 |             {
 96 |                 var excludeList = new HashSet(excludePackageReferenceList);
 97 |                 nuspecDependencyList.RemoveAll(temp => excludeList.Contains(temp.Id));
 98 |             }
 99 | 
100 |             return nuspecDependencyList;
101 |         }
102 | 
103 |         private static List ParserPackageVersion(string packageVersionFile,
104 |             List sourceYardPackageReferenceList, ILogger logger)
105 |         {
106 |             // 包含在 sdk 的库,这些库不应该加入引用
107 |             string[] frameworkSDKNugetList = new[]
108 |             {
109 |                 "Microsoft.NETCore.App",
110 |                 "Microsoft.NETCore.Platforms"
111 |             };
112 | 
113 |             var nuspecDependencyList = new List();
114 |             var packageVersionRegex = new Regex(@"Name='(\S+)' Version='([\S|\-]+)' PrivateAssets='(\S*)'");
115 | 
116 |             using (var stream = File.OpenText(packageVersionFile))
117 |             {
118 |                 string? line;
119 |                 while ((line = stream.ReadLine()) != null)
120 |                 {
121 |                     var match = packageVersionRegex.Match(line);
122 |                     if (match.Success)
123 |                     {
124 |                         var name = match.Groups[1].Value;
125 |                         var version = match.Groups[2].Value;
126 |                         var privateAssets = match.Groups[3].Value;
127 | 
128 |                         // 在源代码包如果项目引用的是 private asset 的库,那么就不应该添加引用
129 |                         // 因为源代码是没有框架的依赖,对 sdk 带的库也不添加
130 | 
131 |                         var isPrivateAssetsAll = privateAssets.IndexOf("all", StringComparison.OrdinalIgnoreCase) >= 0;
132 |                         // net45 没有下面方法
133 |                         //var isPrivateAssetsAll = privateAssets.Contains("all", comparer);
134 | 
135 |                         // 解决 https://github.com/dotnet-campus/SourceYard/issues/60
136 |                         // 即使有某个包标记了使用 private asset 是 All 的,但是这个包是一个源代码包,那么打包的时候就需要添加他的引用依赖
137 |                         var includeInSourceYardPackageReference =
138 |                             sourceYardPackageReferenceList.Any(temp =>
139 |                                 temp.Equals(name, StringComparison.OrdinalIgnoreCase));
140 | 
141 |                         if ((!isPrivateAssetsAll || includeInSourceYardPackageReference)
142 |                             && !frameworkSDKNugetList.Contains(name))
143 |                         {
144 |                             nuspecDependencyList.Add(new NuspecDependency()
145 |                             {
146 |                                 Id = name,
147 |                                 Version = version
148 |                             });
149 |                         }
150 |                     }
151 |                     else
152 |                     {
153 |                         logger.Warning($"项目所引用的 NuGet 包包含有无法识别的格式,包信息:{line}");
154 |                     }
155 |                 }
156 |             }
157 | 
158 |             return nuspecDependencyList;
159 |         }
160 | 
161 |     }
162 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/NuspecContexts/NuspecDependency.cs:
--------------------------------------------------------------------------------
 1 | using System.Xml.Serialization;
 2 | 
 3 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts
 4 | {
 5 |     public class NuspecDependency
 6 |     {
 7 |         [XmlAttribute("id", Namespace = "")]
 8 |         public string Id { get; set; } = null!;
 9 | 
10 |         [XmlAttribute(attributeName: "version")]
11 |         public string Version { get; set; } = null!;
12 |     }
13 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/NuspecContexts/NuspecFrameworkAssembly.cs:
--------------------------------------------------------------------------------
 1 | using System.Xml.Serialization;
 2 | 
 3 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts
 4 | {
 5 |     public class NuspecFrameworkAssembly
 6 |     {
 7 |         [XmlAttribute("assemblyName", Namespace = "")]
 8 |         public string AssemblyName { get; set; } = null!;
 9 |         [XmlAttribute("targetFramework")]
10 |         public string TargetFramework { get; set; } = null!;
11 |     }
12 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/NuspecContexts/NuspecGroup.cs:
--------------------------------------------------------------------------------
 1 | using System.Collections.Generic;
 2 | using System.Xml.Serialization;
 3 | 
 4 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts
 5 | {
 6 |     public class NuspecGroup
 7 |     {
 8 |         [XmlAttribute("targetFramework", Namespace = "")]
 9 |         public string TargetFramework { get; set; } = null!;
10 |         [XmlElement(elementName: "dependency")]
11 |         public List Dependencies { set; get; } = new List();
12 |     }
13 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/NuspecContexts/NuspecMetadata.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.Reflection;
  4 | using System.Xml.Serialization;
  5 | 
  6 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts
  7 | {
  8 |     [Serializable]
  9 |     [XmlType(typeName: "metadata", Namespace = "")]
 10 |     public class NuspecMetadata
 11 |     {
 12 |         public NuspecMetadata()
 13 |         {
 14 |             var assembly = Assembly.GetExecutingAssembly();
 15 |             var version = assembly.GetCustomAttribute().InformationalVersion;
 16 | 
 17 |             SourceYardPackage = $"SourceYard {version}";
 18 |         }
 19 | 
 20 |         [XmlElement("description")] 
 21 |         public string? Description { set; get; }
 22 | 
 23 |         [XmlArray(elementName: "dependencies", Namespace = "")]
 24 |         [XmlArrayItem(elementName: "group")]
 25 |         public List Dependencies { set; get; } = new List();
 26 | 
 27 |         [XmlArray(elementName: "frameworkAssemblies", Namespace = "")]
 28 |         [XmlArrayItem(elementName: "frameworkAssembly")]
 29 |         public List? FrameworkAssemblies { set; get; }
 30 | 
 31 |         [XmlElement("id")] 
 32 |         public string? Id { get; set; }
 33 | 
 34 |         [XmlElement("copyright")]
 35 |         public string? Copyright
 36 |         {
 37 |             get => _copyright;
 38 |             set
 39 |             {
 40 |                 if (string.IsNullOrWhiteSpace(value))
 41 |                 {
 42 |                     // 不使用空字符串,这样才能解决NuGet提示Copyright不能为空
 43 |                     value = null;
 44 |                 }
 45 | 
 46 |                 _copyright = value;
 47 |             }
 48 |         }
 49 | 
 50 |         [XmlElement("licenseUrl")]
 51 |         public string? PackageLicenseUrl
 52 |         {
 53 |             get => _packageLicenseUrl;
 54 |             set
 55 |             {
 56 |                 if (string.IsNullOrWhiteSpace(value))
 57 |                 {
 58 |                     // 不使用空字符串,这样才能解决NuGet提示licenseUrl不能为空
 59 |                     value = null;
 60 |                 }
 61 | 
 62 |                 _packageLicenseUrl = value;
 63 |             }
 64 |         }
 65 | 
 66 |         [XmlElement("version")]
 67 |         public string? Version { get; set; }
 68 | 
 69 |         [XmlElement("projectUrl")]
 70 |         public string? PackageProjectUrl
 71 |         {
 72 |             get => _packageProjectUrl;
 73 |             set
 74 |             {
 75 |                 if (string.IsNullOrWhiteSpace(value))
 76 |                 {
 77 |                     // 不使用空字符串,这样才能解决NuGet提示PackageProjectUrl不能为空
 78 |                     value = null;
 79 |                 }
 80 | 
 81 |                 _packageProjectUrl = value;
 82 |             }
 83 |         }
 84 | 
 85 |         [XmlElement("iconUrl")]
 86 |         public string? PackageIconUrl
 87 |         {
 88 |             get => _packageIconUrl;
 89 |             set
 90 |             {
 91 |                 if (string.IsNullOrWhiteSpace(value))
 92 |                 {
 93 |                     // 不使用空字符串,这样才能解决NuGet提示PackageProjectUrl不能为空
 94 |                     value = null;
 95 |                 }
 96 | 
 97 |                 _packageIconUrl = value;
 98 |             }
 99 |         }
100 | 
101 |         [XmlElement("tags")]
102 |         public string? PackageTags { get; set; }
103 | 
104 |         [XmlElement("releaseNotes")]
105 |         public string? PackageReleaseNotes { get; set; }
106 | 
107 |         [XmlElement("title")]
108 |         public string? Title { get; set; }
109 | 
110 |         [XmlElement("authors")]
111 |         public string? Authors { get; set; }
112 | 
113 |         [XmlElement("owners")]
114 |         public string? Owner { get; set; }
115 | 
116 |         /// 
117 |         /// 表示 SourceYard 的包
118 |         /// 
119 |         [XmlElement("SourceYardPackage")]
120 |         public string? SourceYardPackage { set; get; }
121 | 
122 |         /// 
123 |         /// 通过这个属性可以在安装源代码包的时候默认选 private assets 这样就可以让安装源代码包的项目被引用的时候,引用的项目不需要再安装源代码包
124 |         /// 
125 |         /// 设置DevelopmentDependency时,不单会设置PrivateAssets为all,同时也会将IncludeAssets设置为runtime; build; native; contentfiles; analyzers; buildtransitive,这会导致不会自动去加载源码包使用的其他nuget库
126 |         /// https://github.com/dotnet-campus/SourceYard/issues/112
127 |         [XmlElement("developmentDependency")]
128 |         public string? DevelopmentDependency { get; set; } = "true";
129 | 
130 |         [XmlElement("repository")]
131 |         public Repository? Repository { set; get; }
132 | 
133 |         private string? _copyright;
134 |         private string? _packageProjectUrl;
135 |         private string? _packageLicenseUrl;
136 |         private string? _packageIconUrl;
137 |     }
138 | 
139 |     [XmlType(typeName: "repository", Namespace = "")]
140 |     public class Repository
141 |     {
142 |         [XmlAttribute(attributeName: "type")]
143 |         public string? Type { set; get; }
144 | 
145 |         [XmlAttribute(attributeName: "url")]
146 |         public string? Url { set; get; }
147 |     }
148 | 
149 |     public class NugetTargetFramework
150 |     {
151 |         [XmlAttribute("targetFramework")]
152 |         public string TargetFramework { get; set; } = ".NETFramework4.5";
153 | 
154 |         [XmlArray(elementName: "dependencies", Namespace = "")]
155 |         [XmlArrayItem(elementName: "dependency")]
156 |         public List Dependencies { set; get; } = new List();
157 |     }
158 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/NuspecFiles/NuspecContexts/NuspecPackage.cs:
--------------------------------------------------------------------------------
 1 | using System.Xml.Serialization;
 2 | 
 3 | namespace dotnetCampus.SourceYard.PackFlow.NuspecFiles.NuspecContexts
 4 | {
 5 |     [XmlType("package")]
 6 |     public class NuspecPackage
 7 |     {
 8 |         [XmlElement("metadata")]
 9 |         public NuspecMetadata? NuspecMetadata { get; set; }
10 |     }
11 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/Package.cs:
--------------------------------------------------------------------------------
 1 | using dotnetCampus.SourceYard.Utils;
 2 | 
 3 | namespace dotnetCampus.SourceYard.PackFlow
 4 | {
 5 |     /// 
 6 |     /// 引用的库
 7 |     /// 
 8 |     public class Package
 9 |     {
10 |         /// 
11 |         public Package(string packageName, ReferenceVersion referenceVersion)
12 |         {
13 |             PackageName = packageName;
14 |             ReferenceVersion = referenceVersion;
15 |         }
16 | 
17 |         /// 
18 |         /// 引用库
19 |         /// 
20 |         public string PackageName { get; }
21 | 
22 |         /// 
23 |         /// 库的版本
24 |         /// 
25 |         public ReferenceVersion ReferenceVersion { get; }
26 |     }
27 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/PackFlow/SourcePacker.cs:
--------------------------------------------------------------------------------
 1 | using System.Collections.Generic;
 2 | using System.IO;
 3 | using System.Linq;
 4 | using dotnetCampus.SourceYard.Context;
 5 | using dotnetCampus.SourceYard.Utils;
 6 | 
 7 | namespace dotnetCampus.SourceYard.PackFlow
 8 | {
 9 |     internal class SourcePacker : IPackFlow
10 |     {
11 |         public void Pack(IPackingContext context)
12 |         {
13 |             context.Logger.Message("开始复制源代码文件");
14 |             var srcFolder = Path.Combine(context.PackingFolder, "src");
15 |             context.Logger.Message("源代码临时复制文件夹 " + srcFolder);
16 |         
17 |             FileSystem.CopyFileList(context.ProjectFolder, srcFolder, context.PackagedProjectFile.GetAllFile().ToList());
18 |             context.Logger.Message("复制源代码文件完成");
19 |         }
20 |     }
21 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Packer.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.IO;
  3 | using System.Linq;
  4 | using dotnetCampus.SourceYard.Context;
  5 | using dotnetCampus.SourceYard.PackFlow;
  6 | using dotnetCampus.SourceYard.Utils;
  7 | 
  8 | namespace dotnetCampus.SourceYard
  9 | {
 10 |     internal class Packer
 11 |     {
 12 |         public Packer
 13 |         (
 14 |             string projectFile,
 15 |             string intermediateDirectory,
 16 |             string packageOutputPath,
 17 |             string packageVersion,
 18 |             string? packageId,
 19 |             BuildProps buildProps,
 20 |             DirectoryInfo commonSourcePackingFolder,
 21 |             MultiTargetingPackageInfo multiTargetingPackageInfo,
 22 |             Logger logger
 23 |         )
 24 |         {
 25 |             Logger = logger;
 26 | 
 27 |             Logger.Message(message: "初始化打包");
 28 | 
 29 |             if (string.IsNullOrEmpty(value: projectFile) || !File.Exists(path: projectFile))
 30 |             {
 31 |                 Logger.Error(message: $"无法从{projectFile}找到项目文件");
 32 |                 return;
 33 |             }
 34 | 
 35 |             if (string.IsNullOrEmpty(value: intermediateDirectory))
 36 |             {
 37 |                 // 这时的文件夹可以不存在
 38 |                 Logger.Error(message: "无法解析文件夹 " + intermediateDirectory);
 39 |                 return;
 40 |             }
 41 | 
 42 |             if (string.IsNullOrEmpty(value: packageOutputPath))
 43 |             {
 44 |                 Logger.Error(message: "打包输出文件夹不能为空");
 45 |                 return;
 46 |             }
 47 | 
 48 |             if (string.IsNullOrEmpty(value: packageVersion))
 49 |             {
 50 |                 Logger.Error(message: "打包版本不能为空");
 51 |                 return;
 52 |             }
 53 | 
 54 |             _projectFile = Path.GetFullPath(path: projectFile);
 55 |             _intermediateDirectory = Path.GetFullPath(path: intermediateDirectory);
 56 |             _packageOutputPath = Path.GetFullPath(path: packageOutputPath);
 57 |             _packageVersion = packageVersion;
 58 |             _multiTargetingPackageInfo = multiTargetingPackageInfo;
 59 |             BuildProps = buildProps;
 60 |             PackageId = packageId;
 61 | 
 62 |             PackagedProjectFile = new PackagedProjectFile
 63 |             (
 64 |                 commonSourcePackingFolder,
 65 |                 //compileFile: GetFile(file: compileFile),
 66 |                 //resourceFile: GetFile(file: resourceFile),
 67 |                 //contentFile: GetFile(file: contentFile),
 68 |                 //embeddedResource: GetFile(file: embeddedResource),
 69 |                 //page: GetFile(file: page),
 70 |                 //applicationDefinition: GetFile(file: applicationDefinition),
 71 |                 //noneFile: GetFile(file: noneFile),
 72 |                 projectFolder: Path.GetDirectoryName(path: _projectFile)!,
 73 |                 buildProps: buildProps
 74 |             );
 75 | 
 76 |             _packers = new IPackFlow[]
 77 |             {
 78 |                 new SourcePacker(),
 79 |                 new AssetsPacker(),
 80 |                 new ItemGroupPacker(),
 81 |                 new NuspecFileGenerator(),
 82 |                 new NuGetPacker(),
 83 |             };
 84 | 
 85 |             Logger.Message(message: "初始化打包完成");
 86 |         }
 87 | 
 88 |         internal void Pack()
 89 |         {
 90 |             Logger.Message("开始打包");
 91 | 
 92 |             var packingFolder = _intermediateDirectory;
 93 |             PrepareEmptyDirectory(packingFolder);
 94 | 
 95 |             var projectFile = _projectFile;
 96 | 
 97 |             var projectName = Path.GetFileNameWithoutExtension(projectFile);
 98 | 
 99 |             if (string.IsNullOrEmpty(projectName))
100 |             {
101 |                 Logger.Error("从项目文件无法拿到项目文件名 " + projectFile);
102 |                 return;
103 |             }
104 | 
105 |             var projectFolder = Path.GetDirectoryName(projectFile);
106 | 
107 |             if (string.IsNullOrEmpty(projectFolder))
108 |             {
109 |                 Logger.Error("无法拿到项目文件所在文件夹");
110 |                 return;
111 |             }
112 | 
113 |             var buildProps = BuildProps;
114 | 
115 |             IPackFlow? current = null;
116 |             try
117 |             {
118 |                 foreach (var packer in _packers)
119 |                 {
120 |                     current = packer;
121 |                     var context = new PackingContext
122 |                     (
123 |                         Logger,
124 |                         projectFile,
125 |                         projectName,
126 |                         PackageId,
127 |                         _packageVersion,
128 |                         _packageOutputPath,
129 |                         packingFolder,
130 |                         PackagedProjectFile,
131 |                         _multiTargetingPackageInfo
132 |                     )
133 |                     {
134 |                         BuildProps = buildProps,
135 |                     };
136 |                     packer.Pack(context);
137 |                 }
138 | 
139 |                 Logger.Message("打包完成");
140 |             }
141 |             catch (PackingException ex)
142 |             {
143 |                 Logger.Error(ex);
144 |             }
145 |             catch (Exception ex)
146 |             {
147 |                 Logger.Error($"生成源码包: {current?.GetType().Name}: {ex}");
148 |             }
149 |         }
150 | 
151 |         private ILogger Logger { get; }
152 |         private string? PackageId { get; }
153 | 
154 |         private readonly string _projectFile = null!;
155 |         private readonly string _intermediateDirectory = null!;
156 | 
157 |         /// 
158 |         /// 最后输出的文件夹
159 |         /// 
160 |         private readonly string _packageOutputPath = null!;
161 | 
162 |         private readonly string _packageVersion = null!;
163 |         private readonly MultiTargetingPackageInfo _multiTargetingPackageInfo;
164 | 
165 |         private readonly IPackFlow[] _packers = null!;
166 | 
167 |         private PackagedProjectFile PackagedProjectFile { get; } = null!;
168 |         private BuildProps BuildProps { get; } = null!;
169 | 
170 |         /// 
171 |         /// 准备一个空白的文件夹用来放文件
172 |         /// 
173 |         /// 
174 |         private void PrepareEmptyDirectory(string directory)
175 |         {
176 |             if (!Directory.Exists(directory))
177 |             {
178 |                 Directory.CreateDirectory(directory);
179 |             }
180 |             else
181 |             {
182 |                 foreach (var fileSystemInfo in new DirectoryInfo(directory)
183 |                     .EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly))
184 |                 {
185 |                     try
186 |                     {
187 |                         if (fileSystemInfo is DirectoryInfo directoryInfo)
188 |                         {
189 |                             directoryInfo.Delete(true);
190 |                         }
191 |                         else if (fileSystemInfo is FileInfo fileInfo)
192 |                         {
193 |                             fileInfo.Delete();
194 |                         }
195 |                     }
196 |                     catch (Exception e)
197 |                     {
198 |                         Logger.Error(e.Message);
199 |                     }
200 |                 }
201 |             }
202 |         }
203 |     }
204 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Program.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Diagnostics;
  3 | using System.IO;
  4 | using System.Linq;
  5 | using dotnetCampus.Cli;
  6 | using dotnetCampus.Cli.Standard;
  7 | using dotnetCampus.SourceYard.Cli;
  8 | using dotnetCampus.SourceYard.Context;
  9 | using dotnetCampus.SourceYard.Utils;
 10 | 
 11 | namespace dotnetCampus.SourceYard
 12 | {
 13 |     internal class Program
 14 |     {
 15 |         private static void Main(string[] args)
 16 |         {
 17 |             MagicTransformMultiTargetingToFirstTarget(args);
 18 | 
 19 |             CommandLine.Parse(args).AddStandardHandlers()
 20 |                 .AddHandler(RunOptionsAndReturnExitCode)
 21 |                 .Run();
 22 |         }
 23 | 
 24 |         /// 
 25 |         /// 更改命令行传入内容,用于方便接入后续步骤
 26 |         /// 
 27 |         /// 
 28 |         private static void MagicTransformMultiTargetingToFirstTarget(string[] args)
 29 |         {
 30 |             var argDict = dotnetCampus.Cli.CommandLine.Parse(args).ToDictionary(
 31 |                             x => x.Key,
 32 |                             x => x.Value?.FirstOrDefault()?.Trim());
 33 |             var targetFrameworks = argDict["TargetFrameworks"];
 34 |             if (targetFrameworks != null && !string.IsNullOrWhiteSpace(targetFrameworks))
 35 |             {
 36 |                 // 这里必须考虑如下情况
 37 |                 /*
 38 |                  * netcoreapp3.1;net45;net6.0
 39 |                  *
 40 |                  * 
 41 |                        all
 42 |                        runtime; build; native; contentfiles; analyzers; buildtransitive
 43 |                    
 44 |                  */
 45 |                 // 为什么只有 net45 才安装?原因是只有单个框架打包才有此需求
 46 |                 // 此时就不合适获取首个,而是应该获取有带打包的
 47 | 
 48 |                 string? firstTargetFramework = null;
 49 | 
 50 |                 var multiTargetingPackageInfoFolder = argDict["MultiTargetingPackageInfoFolder"];
 51 |                 if (multiTargetingPackageInfoFolder != null && !string.IsNullOrEmpty(multiTargetingPackageInfoFolder) &&
 52 |                     Directory.Exists(multiTargetingPackageInfoFolder))
 53 |                 {
 54 |                     var multiTargetingPackageInfo =
 55 |                         new MultiTargetingPackageInfo(new DirectoryInfo(multiTargetingPackageInfoFolder),
 56 |                             targetFrameworks);
 57 |                     firstTargetFramework = multiTargetingPackageInfo.ValidTargetFrameworkPackageInfoList.FirstOrDefault()?.TargetFramework;
 58 |                 }
 59 |                 if(string.IsNullOrEmpty(firstTargetFramework))
 60 |                 {
 61 |                     firstTargetFramework = targetFrameworks.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
 62 |                 }
 63 | 
 64 |                 if (!string.IsNullOrWhiteSpace(firstTargetFramework))
 65 |                 {
 66 |                     for (int i = 0; i < args.Length; i++)
 67 |                     {
 68 |                         args[i] = args[i].Replace("\\SourcePacking\\", $"\\{firstTargetFramework}\\SourcePacking\\");
 69 |                     }
 70 |                 }
 71 |             }
 72 |         }
 73 | 
 74 |         private static void RunOptionsAndReturnExitCode(Options options)
 75 |         {
 76 | #if DEBUG
 77 |             Debugger.Launch();
 78 |             Console.WriteLine(Environment.CommandLine);
 79 | #endif
 80 |             var logger = new Logger();
 81 | 
 82 |             FixOptions(options);
 83 | 
 84 |             try
 85 |             {
 86 |                 logger.Message("Source packaging");
 87 | 
 88 |                 var projectFile = options.ProjectFile;
 89 |                 var multiTargetingPackageInfo = new MultiTargetingPackageInfo(options);
 90 |                 var intermediateDirectory = GetIntermediateDirectory(multiTargetingPackageInfo, options, logger);
 91 |                 // 当前多个不同的框架引用不同的文件还不能支持,因此随意获取一个打包文件夹即可
 92 |                 // 为什么?逻辑上不好解决,其次,安装的项目的兼容性无法处理
 93 |                 // 安装的项目的兼容性无法处理?源代码包有 net45 框架,项目是 net47 框架,如何让项目能兼容使用到 net45 框架?当前没有此生成逻辑 
 94 |                 var sourcePackingFolder = GetCommonSourcePackingFolder(multiTargetingPackageInfo, logger);
 95 |                 var packageOutputPath = options.PackageOutputPath;
 96 |                 if (!string.IsNullOrEmpty(packageOutputPath))
 97 |                 {
 98 |                     packageOutputPath = packageOutputPath.Trim();
 99 |                 }
100 |                 var packageVersion = options.PackageVersion;
101 | 
102 |                 //                logger.Message($@"项目文件 {projectFile}
103 |                 //临时文件{intermediateDirectory}
104 |                 //输出文件{packageOutputPath}
105 |                 //版本{packageVersion}
106 |                 //编译的文件{options.CompileFile}
107 |                 //资源文件{options.ResourceFile}
108 |                 //内容{options.ContentFile}
109 |                 //页面{options.Page}
110 |                 //SourcePackingDirectory: {options.SourcePackingDirectory}");
111 | 
112 |                 var description = ReadFile(options.DescriptionFile);
113 |                 var copyright = ReadFile(options.CopyrightFile);
114 | 
115 |                 var buildProps = new BuildProps(logger)
116 |                 {
117 |                     Authors = options.Authors ?? string.Empty,
118 |                     Company = options.Company ?? string.Empty,
119 |                     Owner = options.Owner ?? options.Authors ?? string.Empty,
120 |                     Copyright = copyright,
121 |                     Description = description,
122 |                     //PackageProjectUrl = options.PackageProjectUrl,
123 |                     //RepositoryType = options.RepositoryType,
124 |                     //RepositoryUrl = options.RepositoryUrl,
125 |                     Title = options.Title,
126 |                     PackageIconUrl = options.PackageIconUrl,
127 |                     PackageLicenseUrl = options.PackageLicenseUrl,
128 |                     PackageReleaseNotes = options.PackageReleaseNotesFile,
129 |                     PackageTags = options.PackageTags
130 |                 };
131 | 
132 |                 buildProps.SetSourcePackingDirectory(sourcePackingFolder.FullName);
133 | 
134 |                 var packer = new Packer
135 |                 (
136 |                     projectFile: projectFile,
137 |                     intermediateDirectory: intermediateDirectory,
138 |                     packageOutputPath: packageOutputPath,
139 |                     packageVersion: packageVersion,
140 |                     // 不再从 options 读取,多个框架的情况下,需要各自获取
141 |                     //compileFile: options.CompileFile,
142 |                     //resourceFile: options.ResourceFile,
143 |                     //contentFile: options.ContentFile,
144 |                     //page: options.Page,
145 |                     //applicationDefinition: options.ApplicationDefinition,
146 |                     //noneFile: options.None,
147 |                     //embeddedResource: options.EmbeddedResource,
148 |                     packageId: options.PackageId,
149 |                     buildProps: buildProps,
150 |                     commonSourcePackingFolder: sourcePackingFolder,
151 |                     multiTargetingPackageInfo: multiTargetingPackageInfo,
152 |                     // 多框架下,每个框架有自己的引用路径
153 |                     //packageReferenceVersion: options.PackageReferenceVersion
154 |                     logger: logger
155 |                 );
156 | 
157 |                 packer.Pack();
158 |             }
159 |             catch (Exception e)
160 |             {
161 |                 logger.Error(e.Message);
162 |             }
163 | 
164 |             string ReadFile(string? file)
165 |             {
166 |                 if (string.IsNullOrEmpty(file))
167 |                 {
168 |                     return "";
169 |                 }
170 | 
171 |                 file = Path.GetFullPath(file!);
172 |                 if (File.Exists(file))
173 |                 {
174 |                     try
175 |                     {
176 |                         return File.ReadAllText(file);
177 |                     }
178 |                     catch (Exception e)
179 |                     {
180 |                         logger.Error(e.Message);
181 |                     }
182 |                 }
183 | 
184 |                 return "";
185 |             }
186 |         }
187 | 
188 |         /// 
189 |         /// 兼容修复
190 |         /// 
191 |         /// 
192 |         private static void FixOptions(Options options)
193 |         {
194 |             if (string.IsNullOrWhiteSpace(options.MultiTargetingPackageInfoFolder))
195 |             {
196 |                 // 如果多框架是空的字符串或者是空的,为了后续的判断方便,统一设置为空值
197 |                 options.MultiTargetingPackageInfoFolder = null!;
198 |             }
199 |         }
200 | 
201 |         /// 
202 |         /// 获取通用的 SourcePacking 文件夹,无视框架版本的不同
203 |         /// 
204 |         /// 
205 |         private static DirectoryInfo GetCommonSourcePackingFolder(MultiTargetingPackageInfo multiTargetingPackageInfo, Logger logger)
206 |         {
207 |             // 获取时,需要判断文件夹是否合法
208 |             var fileList = multiTargetingPackageInfo.ValidTargetFrameworkPackageInfoList;
209 | 
210 |             if (fileList.Count == 0)
211 |             {
212 |                 logger.Error($"Can not find any TargetFramework info file from \"{multiTargetingPackageInfo.MultiTargetingPackageInfoFolder.FullName}\"");
213 |                 Exit(-1);
214 |             }
215 | 
216 |             // 如果是单个框架的项目,那么返回即可
217 |             if (fileList.Count == 1)
218 |             {
219 |                 return fileList[0].SourcePackingFolder;
220 |             }
221 |             else
222 |             {
223 |                 return fileList[0].SourcePackingFolder;
224 |             }
225 |         }
226 | 
227 |         private static string GetIntermediateDirectory(MultiTargetingPackageInfo multiTargetingPackageInfo, Options options, Logger logger)
228 |         {
229 |             // 多框架和单个框架的逻辑不相同
230 |             var folder = options.MultiTargetingPackageInfoFolder;
231 |             folder = Path.GetFullPath(folder);
232 |             const string packageName = "Package";
233 | 
234 |             if (string.IsNullOrWhiteSpace(options.TargetFrameworks))
235 |             {
236 |                 // 单个框架的项目
237 |                 var sourcePackingFolder = GetCommonSourcePackingFolder(multiTargetingPackageInfo, logger);
238 |                 // 预期是输出 obj\Debug\SourcePacking\Package 文件
239 |                 var intermediateFolder = Path.Combine(sourcePackingFolder.FullName, packageName);
240 |                 return intermediateFolder;
241 |             }
242 |             else
243 |             {
244 |                 // 多个框架的项目
245 |                 // 输出 obj\Debug\SourceYardMultiTargetingPackageInfoFolder\Package 文件夹
246 |                 return Path.Combine(folder, packageName);
247 |             }
248 |         }
249 | 
250 |         private static void Exit(int code)
251 |         {
252 |             Environment.Exit(code);
253 |         }
254 |     }
255 | }
256 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/BuildProps.cs:
--------------------------------------------------------------------------------
  1 | using System.Collections.Generic;
  2 | using System.IO;
  3 | using System.Linq;
  4 | using dotnetCampus.Configurations;
  5 | using dotnetCampus.Configurations.Core;
  6 | 
  7 | namespace dotnetCampus.SourceYard.Utils
  8 | {
  9 |     /// 
 10 |     /// 构建时用到的属性
 11 |     /// 
 12 |     public class BuildProps
 13 |     {
 14 |         internal BuildProps(ILogger logger)
 15 |         {
 16 |             _logger = logger;
 17 |         }
 18 | 
 19 |         /// 
 20 |         ///     公司
 21 |         /// 
 22 |         public string Company
 23 |         {
 24 |             get
 25 |             {
 26 |                 if (string.IsNullOrEmpty(_company))
 27 |                 {
 28 |                     _company = "dotnet campus";
 29 |                 }
 30 | 
 31 |                 return _company!;
 32 |             }
 33 |             set => _company = value;
 34 |         }
 35 | 
 36 |         /// 
 37 |         ///     作者
 38 |         /// 
 39 |         public string Authors
 40 |         {
 41 |             get
 42 |             {
 43 |                 if (string.IsNullOrEmpty(_authors))
 44 |                 {
 45 |                     _authors = Owner;
 46 |                 }
 47 | 
 48 |                 return _authors!;
 49 |             }
 50 |             set => _authors = value;
 51 |         }
 52 | 
 53 |         /// 
 54 |         ///     仓库地址
 55 |         /// 
 56 |         /// 在 SourceProjectPackageFile.txt 设置
 57 |         public string? RepositoryUrl { get; private set; }
 58 | 
 59 |         public string? RepositoryType { get; private set; }
 60 | 
 61 |         /// 
 62 |         ///     项目地址
 63 |         /// 
 64 |         /// 在 SourceProjectPackageFile.txt 设置
 65 |         public string? PackageProjectUrl { get; private set; }
 66 | 
 67 |         /// 
 68 |         ///     版权
 69 |         /// 
 70 |         public string? Copyright { get; set; }
 71 | 
 72 |         /// 
 73 |         ///     描述
 74 |         /// 
 75 |         public string Description
 76 |         {
 77 |             get
 78 |             {
 79 |                 if (string.IsNullOrEmpty(_description))
 80 |                 {
 81 |                     _description = "This package is built by SourceYard";
 82 |                 }
 83 | 
 84 |                 return _description!;
 85 |             }
 86 |             set => _description = value;
 87 |         }
 88 | 
 89 |         public string Owner
 90 |         {
 91 |             get
 92 |             {
 93 |                 if (string.IsNullOrEmpty(_owner))
 94 |                 {
 95 |                     _owner = "dotnet campus";
 96 |                 }
 97 | 
 98 |                 return _owner!;
 99 |             }
100 |             set => _owner = value;
101 |         }
102 | 
103 |         public string? Title { get; set; }
104 | 
105 |         public string? PackageLicenseUrl { get; set; }
106 | 
107 |         public string? PackageIconUrl { get; set; }
108 | 
109 |         public string? PackageReleaseNotes { get; set; }
110 | 
111 |         public string? PackageTags { get; set; }
112 | 
113 |         /// 
114 |         /// 打包用到的文件夹
115 |         /// 
116 |         public string SourcePackingDirectory { get; private set; } = null!;
117 | 
118 |         private string? _authors;
119 |         private string? _company;
120 | 
121 |         private string? _description;
122 |         private string? _owner;
123 | 
124 |         /// 
125 |         /// 设置打包用到的文件夹,设置时将会自动读取文件
126 |         /// 
127 |         /// 
128 |         public void SetSourcePackingDirectory(string packingDirectory)
129 |         {
130 |             _logger.Message($"BuildProps SourcePackingDirectory={packingDirectory}");
131 |             SourcePackingDirectory = packingDirectory;
132 | 
133 |             // 更多信息读取
134 |             var sourceProjectPackageFile = Path.Combine(packingDirectory, "SourceProjectPackageFile.txt");
135 | 
136 |             // 这个文件里面存放使用 fkv 配置
137 |             if (File.Exists(sourceProjectPackageFile))
138 |             {
139 |                 var fileConfigurationRepo = ConfigurationFactory.FromFile(sourceProjectPackageFile);
140 | 
141 |                 IAppConfigurator appConfigurator = fileConfigurationRepo.CreateAppConfigurator();
142 |                 var configuration = appConfigurator.Default;
143 | 
144 |                 // ReSharper disable ExplicitCallerInfoArgument
145 |                 RepositoryType = configuration.GetValue("RepositoryType")?.Trim() ?? string.Empty;
146 | 
147 |                 PackageProjectUrl = configuration.GetValue("PackageProjectUrl")?.Trim() ?? string.Empty;
148 | 
149 |                 RepositoryUrl = configuration.GetValue("RepositoryUrl")?.Trim() ?? string.Empty;
150 |             }
151 | 
152 |             // 安装的源代码包列表
153 |             const string sourceYardPackageReferenceFile = "SourceYardPackageReferenceFile.txt";
154 |             SourceYardPackageReferenceList = GetList(sourceYardPackageReferenceFile);
155 | 
156 |             // 排除的依赖引用列表
157 |             const string sourceYardExcludePackageReferenceFile =
158 |                 "SourceYardExcludePackageReferenceFile.txt";
159 |             SourceYardExcludePackageReferenceList = GetList(sourceYardExcludePackageReferenceFile);
160 | 
161 |             // 排除的文件引用列表,这些文件将不会被打入源代码包
162 |             const string sourceYardExcludeFileItemFile = "SourceYardExcludeFileItemFile.txt";
163 |             SourceYardExcludeFileItemList = GetList(sourceYardExcludeFileItemFile);
164 |         }
165 | 
166 |         /// 
167 |         /// 排除的文件引用列表
168 |         /// 
169 |         /// 不要在 SourceYard 里面包含的文件项,这些文件项将在打包时被排除
170 |         /// 例如有一些文档是写入到项目里面,期望打包的时候,不要将这些文档作为源代码包的引用,以免被输出,或者干扰调试
171 |         /// 这里面存放的是相对项目的相对路径的文件列表
172 |         public List SourceYardExcludeFileItemList { get; private set; } = null!;
173 | 
174 |         /// 
175 |         /// 排除的依赖引用列表
176 |         /// 
177 |         /// 有某些 NuGet 引用不想作为源代码的依赖,可以添加到 SourceYardExcludePackageReference 列表
178 |         public List SourceYardExcludePackageReferenceList { get; private set; } = null!;
179 | 
180 |         /// 
181 |         /// 安装的源代码包列表
182 |         /// 
183 |         /// 用于解决 https://github.com/dotnet-campus/SourceYard/issues/60
184 |         public List SourceYardPackageReferenceList { get; private set; } = null!;
185 | 
186 |         private List GetList(string fileName)
187 |         {
188 |             var file = Path.Combine(SourcePackingDirectory, fileName);
189 | 
190 |             if (!File.Exists(file))
191 |             {
192 |                 var sourcePackingDirectory = Directory.CreateDirectory(SourcePackingDirectory);
193 |                 _logger.Warning(
194 |                     $"BuildProps Can not find file={file}  SourcePackingDirectory FileList={string.Join(";", sourcePackingDirectory.GetFiles().Select(temp => temp.Name))}");
195 | 
196 |                 return new List(0);
197 |             }
198 | 
199 |             return File.ReadAllLines(file).Where(temp => !string.IsNullOrEmpty(temp)).ToList();
200 |         }
201 | 
202 |         private readonly ILogger _logger;
203 |     }
204 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/CombineReadonlyList.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | using System.Collections;
 3 | using System.Collections.Generic;
 4 | using System.Linq;
 5 | 
 6 | namespace dotnetCampus.SourceYard.Utils
 7 | {
 8 |     public class CombineReadonlyList : IReadOnlyList
 9 |     {
10 |         public CombineReadonlyList(params IReadOnlyList[] source)
11 |         {
12 |             Source = source;
13 |         }
14 | 
15 |         public IReadOnlyList[] Source { get; }
16 | 
17 |         public IEnumerator GetEnumerator()
18 |         {
19 |             foreach (var list in Source)
20 |             {
21 |                 foreach (var temp in list)
22 |                 {
23 |                     yield return temp;
24 |                 }
25 |             }
26 |         }
27 | 
28 |         IEnumerator IEnumerable.GetEnumerator()
29 |         {
30 |             return GetEnumerator();
31 |         }
32 | 
33 |         public int Count => Source.Sum(temp => temp.Count);
34 | 
35 |         public T this[int index]
36 |         {
37 |             get
38 |             {
39 |                 var n = index;
40 |                 var source = Source;
41 | 
42 |                 foreach (var list in source)
43 |                 {
44 |                     if (n < list.Count)
45 |                     {
46 |                         return list[n];
47 |                     }
48 | 
49 |                     n -= list.Count;
50 |                 }
51 | 
52 |                 throw new IndexOutOfRangeException();
53 |             }
54 |         }
55 |     }
56 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/FileSystem.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.Collections.Generic;
  3 | using System.Diagnostics;
  4 | using System.IO;
  5 | using System.Linq;
  6 | using dotnetCampus.SourceYard.Context;
  7 | 
  8 | namespace dotnetCampus.SourceYard.Utils
  9 | {
 10 |     internal static class FileSystem
 11 |     {
 12 |         /// 
 13 |         /// 复制文件列表
 14 |         /// 
 15 |         /// 
 16 |         /// 
 17 |         /// 
 18 |         public static void CopyFileList(string sourceFolder, string targetFolder, List fileList)
 19 |         {
 20 |             foreach (var file in fileList)
 21 |             {
 22 |                 //var relativePath = MakeRelativePath(sourceFolder, file);
 23 |                 var targetFile = Path.GetFullPath(Path.Combine(targetFolder, file.SourcePackagePath));
 24 |                 var directory = Path.GetDirectoryName(targetFile);
 25 |                 if (directory != null && !Directory.Exists(directory))
 26 |                 {
 27 |                     Directory.CreateDirectory(directory);
 28 |                 }
 29 | 
 30 |                 File.Copy(file.SourceFile.FullName, targetFile, true);
 31 |             }
 32 |         }
 33 | 
 34 |         internal static void CopyFolderContents(string sourceFolder, string targetFolder,
 35 |             Func? nameConverter = null, IList? excludes = null)
 36 |         {
 37 |             var sourceDirectory = new DirectoryInfo(sourceFolder);
 38 |             foreach (var directory in sourceDirectory.EnumerateDirectories().Where(
 39 |                 x => excludes?.Contains(x.Name) != true))
 40 |             {
 41 |                 CopyFiles(directory.FullName, Path.Combine(targetFolder, directory.Name), SearchOption.AllDirectories,
 42 |                     nameConverter);
 43 |             }
 44 | 
 45 |             CopyFiles(sourceDirectory.FullName, targetFolder, SearchOption.TopDirectoryOnly, nameConverter);
 46 |         }
 47 | 
 48 |         /// 
 49 |         /// 忽略的文件夹列表
 50 |         /// 
 51 |         internal static IList IgnoreFolderList { set; get; } = new List();
 52 | 
 53 |         /// 
 54 |         /// 忽略的文件后缀列表
 55 |         /// 
 56 |         internal static IList IgnoreFileEndList { set; get; } = new List();
 57 | 
 58 |         private static void CopyFiles(string sourceFolder, string targetFolder, SearchOption searchOption,
 59 |             Func? nameConverter = null)
 60 |         {
 61 |             foreach (var file in new DirectoryInfo(sourceFolder).EnumerateFiles("*", searchOption))
 62 |             {
 63 |                 // 如果是忽略的文件夹,就直接忽略
 64 |                 if (IsIgnoreFolder(file) || IsIgnoredFile(file))
 65 |                 {
 66 |                     continue;
 67 |                 }
 68 | 
 69 |                 var relativePath = MakeRelativePath(sourceFolder, file.FullName);
 70 |                 var targetFile = Path.GetFullPath(Path.Combine(targetFolder, relativePath));
 71 |                 var directory = Path.GetDirectoryName(targetFile);
 72 |                 if (directory != null && !Directory.Exists(directory))
 73 |                 {
 74 |                     Directory.CreateDirectory(directory);
 75 |                 }
 76 | 
 77 |                 var fileName = Path.GetFileName(targetFile);
 78 |                 if (nameConverter != null)
 79 |                 {
 80 |                     fileName = nameConverter(fileName);
 81 |                     targetFile = Path.Combine(Path.GetDirectoryName(targetFile) ?? throw new InvalidOperationException(), fileName);
 82 |                 }
 83 | 
 84 |                 File.Copy(file.FullName, targetFile, true);
 85 |             }
 86 |         }
 87 | 
 88 |         /// 
 89 |         /// 是否是忽略的文件
 90 |         /// 
 91 |         /// 
 92 |         private static bool IsIgnoredFile(FileInfo file)
 93 |         {
 94 |             var name = file.Name;
 95 | 
 96 |             if (IgnoreFileEndList == null)
 97 |             {
 98 |                 return false;
 99 |             }
100 | 
101 |             foreach (var temp in IgnoreFileEndList)
102 |             {
103 |                 if (name.EndsWith(temp, StringComparison.CurrentCultureIgnoreCase))
104 |                 {
105 |                     return true;
106 |                 }
107 |             }
108 | 
109 |             return false;
110 |         }
111 | 
112 |         private static bool IsIgnoreFolder(FileInfo file)
113 |         {
114 |             var directory = file.Directory;
115 |             Debug.Assert(directory != null);
116 |             var name = directory?.Name;
117 | 
118 |             if (string.IsNullOrEmpty(name))
119 |             {
120 |                 return false;
121 |             }
122 | 
123 |             if (IgnoreFolderList == null)
124 |             {
125 |                 return false;
126 |             }
127 | 
128 |             foreach (var temp in IgnoreFolderList)
129 |             {
130 |                 if (name!.Equals(temp, StringComparison.CurrentCultureIgnoreCase))
131 |                 {
132 |                     return true;
133 |                 }
134 |             }
135 | 
136 |             return false;
137 |         }
138 | 
139 |         private static string MakeRelativePath(string fromPath, string toPath)
140 |         {
141 |             if (string.IsNullOrEmpty(fromPath))
142 |             {
143 |                 throw new ArgumentNullException(nameof(fromPath));
144 |             }
145 | 
146 |             if (string.IsNullOrEmpty(toPath))
147 |             {
148 |                 throw new ArgumentNullException(nameof(toPath));
149 |             }
150 | 
151 |             var fromUri = new Uri(fromPath);
152 |             var toUri = new Uri(toPath);
153 | 
154 |             if (fromUri.Scheme != toUri.Scheme)
155 |             {
156 |                 // 不是同一种路径,无法转换成相对路径。
157 |                 return toPath;
158 |             }
159 | 
160 |             if (fromUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase)
161 |                 && !fromPath.EndsWith("/") && !fromPath.EndsWith("\\"))
162 |             {
163 |                 // 如果是文件系统,则视来源路径为文件夹。
164 |                 fromUri = new Uri(fromPath + Path.DirectorySeparatorChar);
165 |             }
166 | 
167 |             var relativeUri = fromUri.MakeRelativeUri(toUri);
168 |             var relativePath = Uri.UnescapeDataString(relativeUri.ToString());
169 | 
170 |             if (toUri.Scheme.Equals("file", StringComparison.InvariantCultureIgnoreCase))
171 |             {
172 |                 relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
173 |             }
174 | 
175 |             return relativePath;
176 |         }
177 |     }
178 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/ItemGroupElement.cs:
--------------------------------------------------------------------------------
  1 | using System.Collections.Generic;
  2 | using System.IO;
  3 | using System.Linq;
  4 | using System.Xml.Linq;
  5 | using dotnetCampus.SourceYard.Context;
  6 | 
  7 | namespace dotnetCampus.SourceYard.Utils
  8 | {
  9 |     class ItemGroupElement
 10 |     {
 11 |         /// 
 12 |         public ItemGroupElement(PackagedProjectFile contextPackagedProjectFile, string filePath, bool isVisible,
 13 |             string packageGuid)
 14 |         {
 15 |             _contextPackagedProjectFile = contextPackagedProjectFile;
 16 |             _filePath = filePath;
 17 |             _isVisible = isVisible;
 18 |             _packageGuid = packageGuid;
 19 |         }
 20 | 
 21 |         public (XElement itemGroupElement, XElement itemGroupElementOfXaml) GetItemGroup()
 22 |         {
 23 |             var contextPackagedProjectFile = _contextPackagedProjectFile;
 24 |             var compileFileList = contextPackagedProjectFile.CompileFileList.Select(temp => temp.SourcePackagePath)
 25 |                 .ToList();
 26 |             var contentFileList = contextPackagedProjectFile.ContentFileList.Select(temp => temp.SourcePackagePath)
 27 |                 .ToList();
 28 |             var resourceFileList = contextPackagedProjectFile.ResourceFileList.Select(temp => temp.SourcePackagePath)
 29 |                 .ToList();
 30 |             var noneFileList = contextPackagedProjectFile.NoneFileList.Select(temp => temp.SourcePackagePath)
 31 |                 .ToList();
 32 |             var embeddedResource = contextPackagedProjectFile.EmbeddedResourceList.Select(temp => temp.SourcePackagePath)
 33 |                 .ToList();
 34 |             var pageFileList = contextPackagedProjectFile.PageList.Select(temp => temp.SourcePackagePath)
 35 |                 .ToList();
 36 | 
 37 |             var prefix = $"_{_packageGuid}";
 38 | 
 39 |             var elementList = new List();
 40 |             elementList.AddRange(IncludingItemCompileFileToElement(compileFileList, $"{prefix}Compile", false));
 41 |        
 42 |             elementList.AddRange(IncludingItemCompileFileToElement(contentFileList, $"Content", true));
 43 |             elementList.AddRange(IncludingItemCompileFileToElement(embeddedResource, $"EmbeddedResource", true));
 44 |             elementList.AddRange(IncludingItemCompileFileToElement(noneFileList, "None", true));
 45 | 
 46 |             var itemGroupElement = new XElement("ItemGroup", elementList);
 47 | 
 48 |             elementList = new List();
 49 |             elementList.AddRange(XamlItemCompileFileToElement(resourceFileList, $"{prefix}Resource", true));
 50 |             elementList.AddRange(XamlItemCompileFileToElement(pageFileList, $"{prefix}Page", false));
 51 | 
 52 |             var itemGroupElementOfXaml = new XElement("ItemGroup", elementList);
 53 | 
 54 |             return (itemGroupElement, itemGroupElementOfXaml);
 55 |         }
 56 | 
 57 |         private readonly PackagedProjectFile _contextPackagedProjectFile;
 58 |         private readonly string _filePath;
 59 |         private readonly bool _isVisible;
 60 |         private readonly string _packageGuid;
 61 | 
 62 |         private List XamlItemCompileFileToElement(IEnumerable compileFileList, string includingItemTypes,
 63 |             bool copyToOutputDirectory)
 64 |         {
 65 |             var elementList = new List();
 66 | 
 67 |             foreach (var temp in compileFileList)
 68 |             {
 69 |                 var element = new XElement(includingItemTypes);
 70 | 
 71 |                 var file = _filePath + temp;
 72 | 
 73 |                 SetXmlItemElement(element, copyToOutputDirectory, file);
 74 | 
 75 |                 elementList.Add(element);
 76 |             }
 77 | 
 78 |             return elementList;
 79 |         }
 80 | 
 81 |         private List IncludingItemCompileFileToElement(IReadOnlyList compileFileList,
 82 |             string includingItemTypes, bool copyToOutputDirectory)
 83 |         {
 84 |             var elementList = new List();
 85 |             foreach (var temp in compileFileList)
 86 |             {
 87 |                 var element = new XElement(includingItemTypes);
 88 |                 var file = _filePath + temp;
 89 |                 SetItemElement(element, copyToOutputDirectory, file);
 90 | 
 91 |                 elementList.Add(element);
 92 |             }
 93 | 
 94 |             return elementList;
 95 |         }
 96 | 
 97 |         private void SetXmlItemElement(XElement element, bool copyToOutputDirectory, string file)
 98 |         {
 99 |             element.SetAttributeValue("SubType", "Designer");
100 |             element.SetAttributeValue("Generator", "MSBuild:Compile");
101 | 
102 |             // xml 的文件需要放在 XamlPreCompile 之前也就是放在 Target 里无法编译
103 |             // 所以需要 xml 的文件自己添加 Condition 判断当前使用本地文件
104 | 
105 |             SetItemElement(element, copyToOutputDirectory, file);
106 |         }
107 | 
108 | 
109 |         private void SetItemElement(XElement element, bool copyToOutputDirectory, string file)
110 |         {
111 |             element.SetAttributeValue("Include", file);
112 |             //element.SetAttributeValue("Link", "%(RecursiveDir)%(Filename)%(Extension)");
113 | 
114 |             if (_isVisible)
115 |             {
116 |                 element.SetAttributeValue("Visible", "True");
117 |             }
118 |             else
119 |             {
120 |                 element.SetAttributeValue("Visible", "False");
121 |             }
122 | 
123 |             if (copyToOutputDirectory)
124 |             {
125 |                 element.SetAttributeValue("CopyToOutputDirectory", "PreserveNewest");
126 |             }
127 |         }
128 |     }
129 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/ReferenceVersion.cs:
--------------------------------------------------------------------------------
  1 | using System.Text.RegularExpressions;
  2 | 
  3 | namespace dotnetCampus.SourceYard.Utils
  4 | {
  5 |     /// 
  6 |     ///     引用的版本
  7 |     /// 用来转换  [2.1.0.293,3.0)、 (1.1.0.3,2.0]、 5.2 的版本
  8 |     /// 
  9 |     public class ReferenceVersion
 10 |     {
 11 |         /// 
 12 |         ///     创建引用版本
 13 |         /// 
 14 |         /// 版本
 15 |         public ReferenceVersion(SemanticVersion? version)
 16 |         {
 17 |             Version = version;
 18 |             MinVersion = version;
 19 |             MaxVersion = version;
 20 |             IsIncludeMaxVersion = true;
 21 |             IsIncludeMinVersion = true;
 22 |         }
 23 | 
 24 |         /// 
 25 |         ///     创建引用版本
 26 |         /// 
 27 |         /// 最低版本
 28 |         /// 最高版本
 29 |         /// 是否包括最低版本
 30 |         /// 是否包括最高版本
 31 |         public ReferenceVersion(SemanticVersion? minVersion, SemanticVersion? maxVersion, bool isIncludeMinVersion,
 32 |             bool isIncludeMaxVersion)
 33 |         {
 34 |             Version = null;
 35 |             MinVersion = minVersion;
 36 |             MaxVersion = maxVersion;
 37 |             IsIncludeMinVersion = isIncludeMinVersion;
 38 |             IsIncludeMaxVersion = isIncludeMaxVersion;
 39 |         }
 40 | 
 41 |         /// 
 42 |         ///     版本
 43 |         /// 
 44 |         public SemanticVersion? Version { get; }
 45 | 
 46 |         /// 
 47 |         ///     最低版本
 48 |         /// 
 49 |         public SemanticVersion? MinVersion { get; }
 50 | 
 51 |         /// 
 52 |         ///     最高版本
 53 |         /// 
 54 |         public SemanticVersion? MaxVersion { get; }
 55 | 
 56 |         /// 
 57 |         ///     是否包括最低版本
 58 |         /// 
 59 |         public bool IsIncludeMinVersion { get; }
 60 | 
 61 |         /// 
 62 |         ///     是否包括最高版本
 63 |         /// 
 64 |         public bool IsIncludeMaxVersion { get; }
 65 | 
 66 |         /// 
 67 |         ///     转换版本
 68 |         /// 
 69 |         /// 
 70 |         /// 
 71 |         public static ReferenceVersion Parser(string str)
 72 |         {
 73 |             if (_regex == null)
 74 |             {
 75 |                 _regex = new Regex(@"([(|\[])([\d|.]*),([\d|.]*)([)|\]])", RegexOptions.Compiled);
 76 |             }
 77 | 
 78 |             var res = _regex.Match(str);
 79 | 
 80 |             if (res.Success)
 81 |             {
 82 |                 var isIncludeMinVersion = res.Groups[1].Value;
 83 |                 var minVersion = res.Groups[2].Value;
 84 |                 var maxVersion = res.Groups[3].Value;
 85 |                 var isIncludeMaxVersion = res.Groups[4].Value;
 86 | 
 87 |                 return new ReferenceVersion
 88 |                 (
 89 |                     string.IsNullOrEmpty(minVersion) ? null : SemanticVersion.Parse(minVersion),
 90 |                     string.IsNullOrEmpty(maxVersion) ? null : SemanticVersion.Parse(maxVersion),
 91 |                     isIncludeMinVersion.Equals("["),
 92 |                     isIncludeMaxVersion.Equals("]")
 93 |                 );
 94 |             }
 95 | 
 96 |             return new ReferenceVersion(SemanticVersion.Parse(str));
 97 |         }
 98 | 
 99 |         private static Regex? _regex;
100 |     }
101 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/SemanticVersion.cs:
--------------------------------------------------------------------------------
  1 | using System;
  2 | using System.ComponentModel;
  3 | using System.Text.RegularExpressions;
  4 | 
  5 | namespace dotnetCampus.SourceYard.Utils
  6 | {
  7 |     /// 
  8 |     ///     语义版本号
  9 |     /// 
 10 |     public class SemanticVersion : IFormattable, IComparable
 11 |     {
 12 |         /// 
 13 |         /// 创建版本号
 14 |         /// 
 15 |         /// 
 16 |         /// 
 17 |         /// 
 18 |         public SemanticVersion(int major = 0, int minor = 0, int patch = 0)
 19 |         {
 20 |             Major = major;
 21 |             Minor = minor;
 22 |             Patch = patch;
 23 |             PreReleaseTag = null;
 24 |             BuildMetaData = null;
 25 |         }
 26 | 
 27 |         /// 
 28 |         /// 创建版本号
 29 |         /// 
 30 |         /// 
 31 |         public SemanticVersion(SemanticVersion semanticVersion)
 32 |         {
 33 |             Major = semanticVersion.Major;
 34 |             Minor = semanticVersion.Minor;
 35 |             Patch = semanticVersion.Patch;
 36 | 
 37 |             PreReleaseTag = semanticVersion.PreReleaseTag;
 38 |             BuildMetaData = semanticVersion.BuildMetaData;
 39 |         }
 40 | 
 41 |         /// 
 42 |         /// 空白版本
 43 |         /// 
 44 |         public static readonly SemanticVersion Empty = new SemanticVersion();
 45 | 
 46 |         private static readonly Regex ParseSemVer = new Regex(
 47 |             @"^(?(?\d+)(\.(?\d+))(\.(?\d+))?)(\.(?\d+))?(-(?[^\+]*))?(\+(?.*))?$",
 48 |             RegexOptions.Compiled);
 49 | 
 50 |         /// 
 51 |         /// 主版本号
 52 |         /// 
 53 |         public int Major { set; get; }
 54 |         /// 
 55 |         /// 次版本号
 56 |         /// 
 57 |         public int Minor { set; get; }
 58 |         public int Patch { set; get; }
 59 |         public string? PreReleaseTag { set; get; }
 60 |         public string? BuildMetaData { set; get; }
 61 | 
 62 |         public bool Equals(SemanticVersion? obj)
 63 |         {
 64 |             if (ReferenceEquals(obj, null))
 65 |             {
 66 |                 return false;
 67 |             }
 68 | 
 69 |             return Major == obj.Major &&
 70 |                    Minor == obj.Minor &&
 71 |                    Patch == obj.Patch &&
 72 |                    PreReleaseTag == obj.PreReleaseTag &&
 73 |                    BuildMetaData == obj.BuildMetaData;
 74 |         }
 75 | 
 76 |         public bool IsEmpty()
 77 |         {
 78 |             return Equals(Empty);
 79 |         }
 80 | 
 81 |         public override bool Equals(object obj)
 82 |         {
 83 |             if (ReferenceEquals(null, obj))
 84 |             {
 85 |                 return false;
 86 |             }
 87 | 
 88 |             if (ReferenceEquals(this, obj))
 89 |             {
 90 |                 return true;
 91 |             }
 92 | 
 93 |             if (obj.GetType() != GetType())
 94 |             {
 95 |                 return false;
 96 |             }
 97 | 
 98 |             return Equals((SemanticVersion) obj);
 99 |         }
100 | 
101 |         public override int GetHashCode()
102 |         {
103 |             unchecked
104 |             {
105 |                 var hashCode = Major;
106 |                 hashCode = (hashCode * 397) ^ Minor;
107 |                 hashCode = (hashCode * 397) ^ Patch;
108 |                 hashCode = (hashCode * 397) ^ (PreReleaseTag != null ? PreReleaseTag.GetHashCode() : 0);
109 |                 hashCode = (hashCode * 397) ^ (BuildMetaData != null ? BuildMetaData.GetHashCode() : 0);
110 |                 return hashCode;
111 |             }
112 |         }
113 | 
114 |         public static bool operator ==(SemanticVersion v1, SemanticVersion v2)
115 |         {
116 |             if (ReferenceEquals(v1, null))
117 |             {
118 |                 return ReferenceEquals(v2, null);
119 |             }
120 | 
121 |             return v1.Equals(v2);
122 |         }
123 | 
124 |         public static bool operator !=(SemanticVersion v1, SemanticVersion v2)
125 |         {
126 |             return !(v1 == v2);
127 |         }
128 | 
129 |         public static bool operator >(SemanticVersion v1, SemanticVersion v2)
130 |         {
131 |             if (ReferenceEquals(v1, null))
132 |             {
133 |                 throw new ArgumentNullException(nameof(v1));
134 |             }
135 | 
136 |             if (ReferenceEquals(v2, null))
137 |             {
138 |                 throw new ArgumentNullException(nameof(v2));
139 |             }
140 | 
141 |             return v1.CompareTo(v2) > 0;
142 |         }
143 | 
144 |         public static bool operator >=(SemanticVersion v1, SemanticVersion v2)
145 |         {
146 |             if (ReferenceEquals(v1, null))
147 |             {
148 |                 throw new ArgumentNullException(nameof(v1));
149 |             }
150 | 
151 |             if (ReferenceEquals(v2, null))
152 |             {
153 |                 throw new ArgumentNullException(nameof(v2));
154 |             }
155 | 
156 |             return v1.CompareTo(v2) >= 0;
157 |         }
158 | 
159 |         public static bool operator <=(SemanticVersion v1, SemanticVersion v2)
160 |         {
161 |             if (ReferenceEquals(v1, null))
162 |             {
163 |                 throw new ArgumentNullException(nameof(v1));
164 |             }
165 | 
166 |             if (ReferenceEquals(v2, null))
167 |             {
168 |                 throw new ArgumentNullException(nameof(v2));
169 |             }
170 | 
171 |             return v1.CompareTo(v2) <= 0;
172 |         }
173 | 
174 |         public static bool operator <(SemanticVersion? v1, SemanticVersion? v2)
175 |         {
176 |             if (ReferenceEquals(v1, null))
177 |             {
178 |                 throw new ArgumentNullException(nameof(v1));
179 |             }
180 | 
181 |             if (ReferenceEquals(v2, null))
182 |             {
183 |                 throw new ArgumentNullException(nameof(v2));
184 |             }
185 | 
186 |             return v1.CompareTo(v2) < 0;
187 |         }
188 | 
189 |         public static SemanticVersion? Parse(string version, string tagPrefixRegex = "[Vv]")
190 |         {
191 |             if (!TryParse(version, tagPrefixRegex, out var semanticVersion))
192 |             {
193 |                 throw new WarningException($"Failed to parse {version} into a Semantic Version");
194 |             }
195 | 
196 |             return semanticVersion;
197 |         }
198 | 
199 |         public static bool TryParse(string version, string tagPrefixRegex, out SemanticVersion? semanticVersion)
200 |         {
201 |             // 这一句为了替换 EasiNote 中包含占位符的版本号。
202 |             version = version.Replace(".$", "-").Replace("$", "");
203 | 
204 |             // 以下是原始逻辑。
205 |             var match = Regex.Match(version, $"^({tagPrefixRegex})?(?.*)$");
206 | 
207 |             if (!match.Success)
208 |             {
209 |                 semanticVersion = null;
210 |                 return false;
211 |             }
212 | 
213 |             version = match.Groups["version"].Value;
214 |             var parsed = ParseSemVer.Match(version);
215 | 
216 |             if (!parsed.Success)
217 |             {
218 |                 semanticVersion = null;
219 |                 return false;
220 |             }
221 | 
222 |             var semanticVersionBuildMetaData = parsed.Groups["BuildMetaData"].Value;
223 |             var fourthPart = parsed.Groups["FourthPart"];
224 | 
225 |             semanticVersion = new SemanticVersion
226 |             {
227 |                 Major = int.Parse(parsed.Groups["Major"].Value),
228 |                 Minor = parsed.Groups["Minor"].Success ? int.Parse(parsed.Groups["Minor"].Value) : 0,
229 |                 Patch = parsed.Groups["Patch"].Success ? int.Parse(parsed.Groups["Patch"].Value) : 0,
230 |                 PreReleaseTag = parsed.Groups["Tag"].Value,
231 |                 BuildMetaData = semanticVersionBuildMetaData
232 |             };
233 | 
234 |             return true;
235 |         }
236 | 
237 |         public override string ToString()
238 |         {
239 |             return ToString(null);
240 |         }
241 | 
242 |         public SemanticVersion IncrementVersion(VersionField incrementStrategy)
243 |         {
244 |             var incremented = new SemanticVersion(this);
245 |             if (string.IsNullOrEmpty(incremented.PreReleaseTag))
246 |             {
247 |                 switch (incrementStrategy)
248 |                 {
249 |                     case VersionField.None:
250 |                         break;
251 |                     case VersionField.Major:
252 |                         incremented.Major++;
253 |                         incremented.Minor = 0;
254 |                         incremented.Patch = 0;
255 |                         break;
256 |                     case VersionField.Minor:
257 |                         incremented.Minor++;
258 |                         incremented.Patch = 0;
259 |                         break;
260 |                     case VersionField.Patch:
261 |                         incremented.Patch++;
262 |                         break;
263 |                     default:
264 |                         throw new ArgumentOutOfRangeException();
265 |                 }
266 |             }
267 |             else
268 |             {
269 |                 throw new NotImplementedException();
270 |             }
271 | 
272 |             return incremented;
273 |         }
274 | 
275 |         public static explicit operator Version(SemanticVersion version)
276 |         {
277 |             return new Version(version.Major, version.Minor, version.Patch, 0);
278 |         }
279 | 
280 |         public int CompareTo(SemanticVersion? value)
281 |         {
282 |             if (ReferenceEquals(value, null))
283 |             {
284 |                 return 1;
285 |             }
286 | 
287 |             if (Major != value.Major)
288 |             {
289 |                 if (Major > value.Major)
290 |                 {
291 |                     return 1;
292 |                 }
293 | 
294 |                 return -1;
295 |             }
296 | 
297 |             if (Minor != value.Minor)
298 |             {
299 |                 if (Minor > value.Minor)
300 |                 {
301 |                     return 1;
302 |                 }
303 | 
304 |                 return -1;
305 |             }
306 | 
307 |             if (Patch != value.Patch)
308 |             {
309 |                 if (Patch > value.Patch)
310 |                 {
311 |                     return 1;
312 |                 }
313 | 
314 |                 return -1;
315 |             }
316 | 
317 |             if (PreReleaseTag != value.PreReleaseTag)
318 |             {
319 |                 if (string.Compare(PreReleaseTag, value.PreReleaseTag, StringComparison.InvariantCulture) > 0)
320 |                 {
321 |                     return 1;
322 |                 }
323 | 
324 |                 return -1;
325 |             }
326 | 
327 |             return 0;
328 |         }
329 | 
330 |         /// 
331 |         ///     s - Default SemVer [1.2.3-beta.4+5]
332 |         ///     f - Full SemVer [1.2.3-beta.4+5]
333 |         ///     i - Informational SemVer [1.2.3-beta.4+5.Branch.master.BranchType.Master.Sha.000000]
334 |         ///     j - Just the SemVer part [1.2.3]
335 |         ///     t - SemVer with the tag [1.2.3-beta.4]
336 |         ///     l - Legacy SemVer tag for systems which do not support SemVer 2.0 properly [1.2.3-beta4]
337 |         ///     lp - Legacy SemVer tag for systems which do not support SemVer 2.0 properly (padded) [1.2.3-beta0004]
338 |         /// 
339 |         public string ToString(string? format, IFormatProvider? formatProvider = null)
340 |         {
341 |             if (string.IsNullOrEmpty(format))
342 |             {
343 |                 format = "s";
344 |             }
345 | 
346 |             if (formatProvider?.GetFormat(GetType()) is ICustomFormatter formatter)
347 |             {
348 |                 return formatter.Format(format, this, formatProvider);
349 |             }
350 | 
351 |             // Check for lp first because the param can varry
352 |             format = format!.ToLower();
353 |             if (format.StartsWith("lp", StringComparison.Ordinal))
354 |             {
355 |                 // handle the padding
356 |                 return !string.IsNullOrEmpty(PreReleaseTag) ? $"{ToString("j")}-{PreReleaseTag}" : ToString();
357 |             }
358 | 
359 |             switch (format)
360 |             {
361 |                 case "j":
362 |                     return $"{Major}.{Minor}.{Patch}";
363 |                 case "s":
364 |                     return !string.IsNullOrEmpty(PreReleaseTag)
365 |                         ? $"{ToString("j")}-{PreReleaseTag}"
366 |                         : ToString("j");
367 |                 case "t":
368 |                     return !string.IsNullOrEmpty(PreReleaseTag)
369 |                         ? $"{ToString("j")}-{PreReleaseTag}"
370 |                         : ToString("j");
371 |                 case "l":
372 |                     return !string.IsNullOrEmpty(PreReleaseTag)
373 |                         ? $"{ToString("j")}-{PreReleaseTag}"
374 |                         : ToString("j");
375 |                 case "f":
376 |                 {
377 |                     var buildMetadata = BuildMetaData;
378 | 
379 |                     return !string.IsNullOrEmpty(buildMetadata)
380 |                         ? $"{ToString("s")}+{buildMetadata}"
381 |                         : ToString("s");
382 |                 }
383 |                 case "i":
384 |                 {
385 |                     var buildMetadata = BuildMetaData;
386 | 
387 |                     return !string.IsNullOrEmpty(buildMetadata)
388 |                         ? $"{ToString("s")}+{buildMetadata}"
389 |                         : ToString("s");
390 |                 }
391 |                 default:
392 |                     throw new ArgumentException($"Unrecognised format '{format}'", "format");
393 |             }
394 |         }
395 |     }
396 | }
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/Utils/VersionField.cs:
--------------------------------------------------------------------------------
 1 | // 请注意:本文件仅为提高 DEBUG 下编译速度而写,请勿开放到 Release 配置下使用!
 2 | // 如果将来有语义版本号需要,可以考虑引用 NuGet 包。
 3 | // SemanticVersion,语义版本号,MIT 开源协议
 4 | // 项目地址:https://github.com/GitTools/GitVersion/blob/master/src/GitVersionCore/SemanticVersion.cs
 5 | 
 6 | namespace dotnetCampus.SourceYard.Utils
 7 | {
 8 |     public enum VersionField
 9 |     {
10 |         None,
11 |         Patch,
12 |         Minor,
13 |         Major
14 |     }
15 | }
16 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/dotnetCampus.SourceYard.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     
 5 |     Exe
 6 |     enable
 7 |     latest
 8 |     net45;netcoreapp2.0
 9 |     $(MSBuildWarningsAsMessages);NETSDK1138
10 |   
11 |   
12 |   
13 |     true
14 |     true
15 |     true
16 |       
17 |     
18 |     
19 |     
20 |     Major
21 |  
22 |     
23 |     
24 |     
25 |   
26 | 
27 |   
28 |     
29 |     
30 |     
31 |     
32 |   
33 | 
34 |   
35 |     
36 |   
37 | 
38 |   
39 |     
40 |     
41 |     
42 |     
43 |       all
44 |       runtime; build; native; contentfiles; analyzers
45 |     
46 | 
47 |     
48 |     
49 |   
50 | 
51 |   
52 |     
53 |     
54 |   
55 | 
56 |   
57 |     
58 |     
59 |       PreserveNewest
60 |     
61 |   
62 | 
63 |     
64 |       
65 |        
66 |         
67 |         
68 |         
69 | 
70 |         
71 |         
72 |         
73 | 
74 |         
75 |         
76 |         
77 |         
78 |         
79 |       
80 |     
81 | 
82 | 
83 | 
--------------------------------------------------------------------------------
/src/dotnetCampus.SourceYard/dotnetCampus.SourceYard.csproj.DotSettings:
--------------------------------------------------------------------------------
1 | 
2 | 	True
3 | 	True
--------------------------------------------------------------------------------
/tests/SourceYardLaunchSettingsDemo/Program.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | 
 3 | namespace SourceYardLaunchSettingsDemo
 4 | {
 5 |     class Program
 6 |     {
 7 |         static void Main(string[] args)
 8 |         {
 9 |             Console.WriteLine("Hello World!");
10 |         }
11 |     }
12 | }
13 | 
--------------------------------------------------------------------------------
/tests/SourceYardLaunchSettingsDemo/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 |   "profiles": {
3 |     "SourceYardLaunchSettingsDemo": {
4 |       "commandName": "Project",
5 |       "commandLineArgs": "lindexi is doubi"
6 |     }
7 |   }
8 | }
--------------------------------------------------------------------------------
/tests/SourceYardLaunchSettingsDemo/SourceYardLaunchSettingsDemo.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     
 4 |         Exe
 5 |         netcoreapp3.1
 6 |     
 7 |     
 8 |         
 9 |             all
10 |             runtime; build; native; contentfiles; analyzers; buildtransitive
11 |         
12 |     
13 | 
14 | 
--------------------------------------------------------------------------------
/tests/SourceYardTestDemo/Program.cs:
--------------------------------------------------------------------------------
 1 | using System;
 2 | 
 3 | namespace SourceYardLaunchSettingsDemo
 4 | {
 5 |     class Program
 6 |     {
 7 |         static void Main(string[] args)
 8 |         {
 9 |             Console.WriteLine("Hello World!");
10 |         }
11 |     }
12 | }
13 | 
--------------------------------------------------------------------------------
/tests/SourceYardTestDemo/SourceYardTestDemo.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |   
 5 | 
 6 |   
 7 |     Exe
 8 |     net5
 9 |   
10 | 
11 |   
12 |     ..\..\src\dotnetCampus.SourceYard\bin\Debug\net45\dotnetCampus.SourceYard.exe
13 |   
14 | 
15 |   
16 |   
17 |     
18 |     
19 |     
20 |   
21 | 
--------------------------------------------------------------------------------
/tests/SourceYardTestDemo/SourceYardTestDemo.sln:
--------------------------------------------------------------------------------
 1 | 
 2 | Microsoft Visual Studio Solution File, Format Version 12.00
 3 | # Visual Studio 15
 4 | VisualStudioVersion = 15.0.26124.0
 5 | MinimumVisualStudioVersion = 15.0.26124.0
 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceYardTestDemo", "SourceYardTestDemo.csproj", "{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}"
 7 | EndProject
 8 | Global
 9 | 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | 		Debug|Any CPU = Debug|Any CPU
11 | 		Debug|x64 = Debug|x64
12 | 		Debug|x86 = Debug|x86
13 | 		Release|Any CPU = Release|Any CPU
14 | 		Release|x64 = Release|x64
15 | 		Release|x86 = Release|x86
16 | 	EndGlobalSection
17 | 	GlobalSection(SolutionProperties) = preSolution
18 | 		HideSolutionNode = FALSE
19 | 	EndGlobalSection
20 | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|x64.ActiveCfg = Debug|Any CPU
24 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|x64.Build.0 = Debug|Any CPU
25 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|x86.ActiveCfg = Debug|Any CPU
26 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Debug|x86.Build.0 = Debug|Any CPU
27 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|Any CPU.Build.0 = Release|Any CPU
29 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|x64.ActiveCfg = Release|Any CPU
30 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|x64.Build.0 = Release|Any CPU
31 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|x86.ActiveCfg = Release|Any CPU
32 | 		{7E80935C-6460-4DEC-8AA2-57CFB1BC2758}.Release|x86.Build.0 = Release|Any CPU
33 | 	EndGlobalSection
34 | EndGlobal
35 | 
--------------------------------------------------------------------------------
/tests/dotnetCampus.SourceYard.Tests/dotnetCampus.SourceYard.Tests.csproj:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   
 4 |     netcoreapp2.0
 5 |     false
 6 |     $(MSBuildWarningsAsMessages);NETSDK1138
 7 |   
 8 | 
 9 |   
10 |     
11 |     
12 |     
13 |     
14 |   
15 | 
16 |   
17 |     
18 |   
19 | 
20 | 
21 | 
--------------------------------------------------------------------------------