[dotnet] Add dotnet projects and examples

+ Sitemap generator I created while learning the dispose pattern
+ Testing project for learning general C#
master
Shaun Reed 2 years ago
parent 6dbac7559a
commit d1fb33c58e

@ -7,6 +7,7 @@ github.com/shaunrd0/klips/
├── ansible # Ansible roles, playbooks, and examples ├── ansible # Ansible roles, playbooks, and examples
├── blockchain # Blockchain related project templates and examples ├── blockchain # Blockchain related project templates and examples
├── cpp # C++ programs, datastructures, and other examples ├── cpp # C++ programs, datastructures, and other examples
├── dotnet # .NET projects and examples
├── figlet # Figlet fonts I like :) ├── figlet # Figlet fonts I like :)
├── javascript # Javascript projects and examples ├── javascript # Javascript projects and examples
├── python # Python scripts or tools I've made ├── python # Python scripts or tools I've made

@ -0,0 +1,11 @@
# Dotnet
```bash
shaunrd0/klips/dotnet/
├── sitemap # Custom library to generate sitemaps
├── testing # General .NET practice
└── README.md
```
All of these projects were created with the `dotnet` CLI on Linux (Kubuntu 20.04).
They have not been tested on any other platform.

@ -0,0 +1,454 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\SiteMapLibrary\SiteMapLibrary.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,12 @@
using SiteMapLibrary;
// Create an XmlManager to use for generating our sitemap; Provide a file path (and optional Xml settings; See ctor)
var mgr = new XmlManager("/home/kapper/Code/klips/dotnet/sitemap/ConsoleApp/TestFiles/sitemap.xml");
// If we want to output the sitemap to the console, instead of saving to a file
// var mgr = new XmlManager("Console.Out");
// Provide a base URL to start crawling, an XmlManager, and a Regex pattern to use for matching URLs while crawling
using SiteMap siteMap = new SiteMap("https://knoats.com", mgr,
new("(http?s://knoats.com(?!.*/dist/|.*/settings/|.*/register/|.*/login/|.*/uploads/|.*/export/|.*/search?).*?(?=\"))"));
// Start crawling; When this returns, we have visited all found URLs and wrote them to our sitemap
await siteMap.Crawl();

@ -0,0 +1,9 @@
User-agent: *
Disallow:
Disallow: /dist/
Disallow: /settings/
Disallow: /register/
Disallow: /login/
Disallow: /uploads/
Disallow: /export/
Disallow: /search?

@ -0,0 +1,975 @@
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<loc>https://knoats.com</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/tags</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/login</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/shelves</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/register</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/ansible</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/password/email</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/user/shaun-reed</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c?shelf=2</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/javascript</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/blockchain</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim?shelf=2</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git?shelf=2</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/shelves/containers</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c/page/basics</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/shelves/programming</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker?shelf=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c/page/classes</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim/page/notes</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/ansible?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/page/basics</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack?shelf=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/chapter/usage</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking?shelf=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker/page/gitlab</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker/page/shlink</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin?shelf=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin?shelf=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/page/submodules</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/i3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/dns</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker/page/heimdall</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi/page/installation</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c-s68/page/dotnet-cli</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c/page/multithreading</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/grub</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/javascript/page/webgl</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/arch</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/tcpip</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/nginx</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/link/30#bkmrk-configure-ssl</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/fail2ban</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/apache</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker/page/dockerfile</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/page/authentication</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/debian</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/tcp-udp</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated?page=2</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated?page=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated?page=4</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated?page=5</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi/chapter/magic-mirror</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/pages/recently-updated?page=1</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/blockchain/page/solidity</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/c/page/building-projects</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim/page/configuring-vim</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/bash</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/crontab</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/yakuake</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/chapter/knoats</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/examples</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/xps-9310</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/wireless</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/ossec-rules</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/osi-model</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi/chapter/backup-scripts</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/tunneling</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/subnetting</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/bluetooth</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/ansible/page/creating-roles</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/virtualbox</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/chapter/monitoring</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/chapter/protocols</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi/page/magic-mirror-modules</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/page/software-development</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/boot-process</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/shelves/linux-server-administration</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/prefabs</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/proxy-servers</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/chapter/development</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/chapter/unity</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/bash-profiles</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/configure-ftp</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/interfaces</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/audio-devices</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/server-checklist</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/devsec-baselines</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/chapter/web-servers</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/chapter/installation</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/scripting</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/shortcuts</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/ansible/page/creating-playbooks</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/system-sensors</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications?shelf=3</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/swap-allocation</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/getting-started</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/system-admin</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/server-hostname</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/disk-management</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/pi/page/staging-configs-to-a-usb</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/linux-setup</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/git/page/pushing-merging-branches</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/systemd-services</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/distributions</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/customization</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/installing-fonts</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/virtualbox-networks</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/page/ossec-ubuntu-server</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/security/chapter/server-hardening</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/kernel-management</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/ansible/page/managing-remote-hosts</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/configure-postfix</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/page/hexo</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/mount-google-drive</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/page/gitea</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/enabling-google-2fa</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/user-administration</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/unattended-upgrades</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/page/jekyll</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/welcome-to-knoats-432</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/linux-on-chromebooks</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/post-processing</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/chapter/ssh-configuration</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/exploring-the-database</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/project-settings</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/new-input-system</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/bookstack-configuration</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/docker/chapter/docker-compose-services</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/chapter/unreal-engine-4</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/networking/page/certbot-ssl-certificates</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/yubikey-ssh-authentication</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/page/read-the-docs</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/backup-bookstack-using-docker</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/gameplay-ability-system</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/synchronizing-time-using-ntp</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/bookstack-using-docker-compose</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/chapter/url-shortners</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/bookstack/page/updating-bookstack-using-docker</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/configuring-sshd-authentication</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/chapter/site-generators</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/vim/page/configuring-vim#bkmrk-unicode.vim-plugin</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/game-development/page/retarget-skeleton-animations</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/page/mame-web-application</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/linux-admin/page/configuring-multi-boot-filesystems</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
<url>
<loc>https://knoats.com/books/self-hosted-applications/chapter/documentation-generators</loc>
<lastmod>2022-5-4</lastmod>
<changefreq>daily</changefreq>
<priority>0.5</priority>
</url>
</urlset>

@ -0,0 +1,45 @@
Sitemap generator I created while learning some C#.
Example of using the library is in `ConsoleApp/Program.cs`, files used for testing are in `ConsoleApp/TestFiles/`
`ConsoleApp/TestFiles/sitemap.xml` currently contains the sitemap for my website.
If we run the console application with a different URL that targets this same file, the file will be overwritten with the new sitemap.
There is no need to delete or recreate files manually.
I plan to check for a `robots.txt` while generating sitemaps to prevent crawling pages that aren't useful.
For now there is no use for a `robots.txt`, the `SiteMap.Crawl()` function visits the URL provided to the `SiteMap` constructor.
Regex is used to check the visited page and match URLs with the same base domain, the URLS found are logged for the crawler to visit.
Each time we finish collecting URLS on a page, we move to the next URL in the queue and repeat this process.
Once we finish crawling all URLs, an XML sitemap is generated where the URLs are sorted by their length.
I used [sitemaps.org - XML Format](https://www.sitemaps.org/protocol.html) to determine the proper formatting for the sitemap.
For now, since the web application I used for testing does not respond with [Last-Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Last-Modified) in the HTTP header, the last modified time is set to the date the sitemap was generated.
The `priority` fields are all set to the default value indicated on sitemaps.org, which is `0.5`.
This is to avoid confusing crawlers with a huge list of 'top-priority' pages to crawl.
All `changefreq` fields of the sitemap are marked as `daily`.
The primary motivation for this project was learning about unmanaged resources in C#, and trying out the [Dispose Pattern](https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose?redirectedfrom=MSDN#implement-the-dispose-pattern) for myself.
If someone reading this were to find a problem with the way I handled disposing of the `HttpClient` in the `SiteMap` class, feel free to let me know :) Creating an issue, PR, or sending an email is all acceptable.
### Future plans
* Parse `robots.txt` to avoid crawling pages that are not desired
* Test the generator with an application that serves `LastModified` date; Use it if available
* Set `priority` in a more useful way, or allow some form of customization of the way this is handled.
* Set `changefreq` in a more useful way, or allow some form of customization of the way this is handled.
* Generate a regex pattern to match, if one is not provided
For now, the general use of this library is seen in the example below.
```C#
using SiteMapLibrary;
// Create an XmlManager to use for generating our sitemap; Provide a file path (and optional Xml settings; See ctor)
var mgr = new XmlManager("/home/kapper/Code/klips/dotnet/sitemap/ConsoleApp/TestFiles/sitemap.xml");
// If we want to output the sitemap to the console, instead of saving to a file
// var mgr = new XmlManager("Console.Out");
// Provide a base URL to start crawling, an XmlManager, and a Regex pattern to use for matching URLs while crawling
using SiteMap siteMap = new SiteMap("https://knoats.com", mgr,
new("(http?s://knoats.com(?!.*/dist/|.*/settings/|.*/register/|.*/login/|.*/uploads/|.*/export/|.*/search?).*?(?=\"))"));
// Start crawling; When this returns, we have visited all found URLs and wrote them to our sitemap
await siteMap.Crawl();
```

@ -0,0 +1,114 @@
using System.Text.RegularExpressions;
namespace SiteMapLibrary;
public class SiteMap : IDisposable
{
private HttpClient _client;
private HashSet<string> _foundUrls;
private HashSet<string> _visitedUrls;
private Queue<string> _visitQueue;
private bool _disposed = false;
private XmlManager XmlManager { get; set; }
public string? Url { get; private set; }
public Regex Regexp { get; set; }
public SiteMap(string url, string savepath, Regex pattern)
{
Url = url;
_client = new HttpClient();
_foundUrls = new HashSet<string>();
_visitedUrls = new HashSet<string>();
_visitQueue = new Queue<string>();
Regexp = pattern;
XmlManager = new XmlManager(savepath);
}
public SiteMap(string url, XmlManager mgr, Regex pattern)
{
_client = new HttpClient();
_foundUrls = new HashSet<string>();
_visitedUrls = new HashSet<string>();
_visitQueue = new Queue<string>();
Regexp = pattern;
Url = url;
XmlManager = mgr;
}
public async Task Crawl()
{
while (Url != null)
{
_visitedUrls.Add(Url);
using var content = await _client.GetAsync(Url);
if (!content.IsSuccessStatusCode)
{
Console.WriteLine($"{content.StatusCode} on url: {Url}");
NextUrl();
continue;
}
var m = Regexp.Match(await content.Content.ReadAsStringAsync());
while (m.Success)
{
foreach (Group group in m.Groups)
{
if (_foundUrls.Add(group.Value))
{
Console.WriteLine(group.Value);
// Console.WriteLine(content.Content.Headers.LastModified);
if (!_visitedUrls.Contains(group.Value) && !_visitQueue.Contains(group.Value))
{
_visitQueue.Enqueue(group.Value);
}
}
}
m = m.NextMatch();
}
NextUrl();
content.Dispose();
}
WriteXml();
}
private void WriteXml()
{
List<string> urls = new List<string>(_visitedUrls.OrderBy(k => k.Length).ToArray());
foreach (string url in urls)
{
XmlManager.AddUrl(url);
}
XmlManager.Save();
}
private void NextUrl()
{
if (_visitQueue.Count == 0)
{
Url = null;
return;
}
Url = _visitQueue.Dequeue();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_client.Dispose();
}
_disposed = true;
}
}
}

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>SiteMap</RootNamespace>
</PropertyGroup>
</Project>

@ -0,0 +1,59 @@
using System.Xml;
namespace SiteMapLibrary;
public class XmlManager
{
private XmlDocument XmlDocument { get; set; }
private XmlDeclaration XmlDeclaration { get; set; }
private XmlElement XmlUrlset { get; set; }
private string Path { get; set; }
public XmlManager(string path,
string version="1.0", string encoding="utf-8", string standalone="")
{
XmlDocument = new XmlDocument();
XmlDeclaration = XmlDocument.CreateXmlDeclaration(version, encoding, standalone);
XmlDocument.AppendChild(XmlDeclaration);
XmlUrlset = XmlDocument.CreateElement("urlset");
XmlDocument.AppendChild(XmlUrlset);
Path = path;
}
~XmlManager()
{
Save();
}
public void AddUrl(string url)
{
XmlElement newUrl = XmlDocument.CreateElement("url");
XmlUrlset.AppendChild(newUrl);
XmlElement newLoc = XmlDocument.CreateElement("loc");
newLoc.InnerText = url;
newUrl.AppendChild(newLoc);
var lastmod = XmlDocument.CreateElement("lastmod");
lastmod.InnerText = DateTime.Now.Year.ToString()
+ '-' + DateTime.Now.Month.ToString()
+ '-' + DateTime.Now.Day;
newUrl.AppendChild(lastmod);
var changeFreq = XmlDocument.CreateElement("changefreq");
changeFreq.InnerText = "daily";
newUrl.AppendChild(changeFreq);
var priority = XmlDocument.CreateElement("priority");
priority.InnerText = "0.5";
newUrl.AppendChild(priority);
}
public void Save()
{
if (Path == "Console.Out")
{
XmlDocument.Save(Console.Out);
}
else
{
XmlDocument.Save(Path);
}
}
}

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SiteMapLibrary", "SiteMapLibrary\SiteMapLibrary.csproj", "{0BDEDA94-7BBF-4F82-9A14-131C4F8A3330}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "ConsoleApp\ConsoleApp.csproj", "{600802AC-C872-4115-BFE6-DA2AE7138F9C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0BDEDA94-7BBF-4F82-9A14-131C4F8A3330}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BDEDA94-7BBF-4F82-9A14-131C4F8A3330}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BDEDA94-7BBF-4F82-9A14-131C4F8A3330}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BDEDA94-7BBF-4F82-9A14-131C4F8A3330}.Release|Any CPU.Build.0 = Release|Any CPU
{600802AC-C872-4115-BFE6-DA2AE7138F9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{600802AC-C872-4115-BFE6-DA2AE7138F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{600802AC-C872-4115-BFE6-DA2AE7138F9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{600802AC-C872-4115-BFE6-DA2AE7138F9C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

@ -0,0 +1,454 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET
project.lock.json
project.fragment.lock.json
artifacts/
# Tye
.tye/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
##
## Visual studio for Mac
##
# globs
Makefile.in
*.userprefs
*.usertasks
config.make
config.status
aclocal.m4
install-sh
autom4te.cache/
*.tar.gz
tarballs/
test-results/
# Mac bundle stuff
*.dmg
*.app
# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# JetBrains Rider
.idea/
*.sln.iml
##
## Visual Studio Code
##
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\KlipsLibrary\KlipsLibrary.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,14 @@
using KlipsLibrary;
Klips.SayHello();
int[] arr = { 2, 4, 6, 2, 1, 44, 10 };
Klips.Print(arr);
Console.WriteLine();
HashSet<string> set = new HashSet<string>(){ "hi", "my", "name", "is", "shaun" };
Klips.Print(set);
Console.WriteLine();
// Test other C# containers
Klips.TestContainers();

@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KlipsLibrary\KlipsLibrary.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,22 @@
using Xunit;
namespace KlipsLibrary.Test;
public class UnitTest1
{
[Fact]
public void DogTest()
{
var dog = new Dog("Buford", "Woof");
Assert.Equal("Buford", dog.Name);
dog.Speak();
}
[Fact]
public void HumanTest()
{
var human = new Human("Shaun", "Hi");
Assert.Equal("Shaun", human.Name);
human.Speak();
}
}

@ -0,0 +1,70 @@
using System.Collections;
using KlipsLibrary;
namespace KlipsLibrary;
public class Solution {
public int NumUniqueEmails(string[] emails)
{
HashSet<string> sent = new();
foreach (var email in emails)
{
var domain = email.Substring(email.IndexOf("@"), email.Length);
var to = email.Substring(0, email.IndexOf("@"));
if (to.Contains(".")) to = to.Replace(".", "");
to = to.Remove(to.IndexOf("+"));
Console.Write("{0} at {1}", to, domain);
sent.Add(to + "@" + domain);
}
return sent.Count;
}
}
public abstract class Animal
{
public Animal(string n, string p)
{
this.Name = n;
this.Phrase = p;
}
public abstract void Speak();
private string name;
public string Name { get; set; }
private string phrase;
public string Phrase { get; set; }
}
public class Dog : Animal
{
public Dog(string n, string p) : base(n, p) { }
public override void Speak()
{
Console.WriteLine("{0} (Dog): {1}", Name, Phrase);
}
}
public class Human : Animal
{
public Human(string n, string p) : base(n, p) { }
public override void Speak()
{
Console.WriteLine("{0} (Human): {1}", Name, Phrase);
}
}
public class Teacher : Human, IComparable, ICloneable
{
public Teacher(string n, string p) : base(n, p) { }
public int CompareTo(object? obj)
{
throw new NotImplementedException();
}
public object Clone()
{
throw new NotImplementedException();
}
}

@ -0,0 +1,74 @@
namespace KlipsLibrary;
public struct Item : IEquatable<Item>
{
public Item(double v, int q, string name)
{
Value = v;
Qty = q;
Name = name;
}
public Item(double v, string name)
{
Value = v;
Qty = 1;
Name = name;
}
public string Name { get; set; }
public double Value { get; set; }
public int Qty { get; set; }
public static bool operator ==(Item a, Item b)
{
if (((object)a) == null || ((object)b) == null) return Object.Equals(a, b);
return a.Equals(b);
}
public static bool operator !=(Item a, Item b)
{
return !(a == b);
}
public bool Equals(Item other)
{
return Name == other.Name && Value == other.Value;
}
public override bool Equals(object? obj)
{
return obj is Item other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(Name, Value);
}
}
public class Bag
{
public Bag()
{
contents = new List<Item>();
maxCarry = 10;
}
private List<Item> contents;
private int maxCarry;
public bool AddItem(Item i)
{
if (contents.Count >= maxCarry) return false;
contents.Add(i);
return true;
}
public Item? TakeItem(Item i)
{
var found = contents.Find((Item inBag) => inBag == i);
if (found == default(Item)) return null;
contents.Remove(found);
return found;
}
}

@ -0,0 +1,19 @@
using System.Collections.ObjectModel;
namespace KlipsLibrary;
public class Fruit
{
public Fruit()
{
Name = "Default";
}
public Fruit(string name)
{
Name = name;
}
public string Name { get; set; }
}
public class Fruits : Collection<Fruit> { }

@ -0,0 +1,75 @@
namespace KlipsLibrary;
public class A
{
public A()
{
Console.WriteLine("A default constructor was called");
Val = 0;
}
public A(int v)
{
Console.WriteLine("A parameterized constructor was called");
Val = v;
}
private int val;
public int Val
{
// No setter; We can only initialize on construction
init
{
Console.WriteLine($"A.val was initialized: {val}");
val = value;
}
}
}
public class B : A
{
public B()
{
Console.WriteLine("B default constructor was called");
BVal = 0;
}
public B(int bv)
{
Console.WriteLine("B parameterized constructor was called");
BVal = bv;
}
private int bVal;
public int BVal
{
init
{
bVal = value;
Console.WriteLine($"B.bVal was initialized: {bVal}");
}
}
}
public class C : B
{
public C()
{
Console.WriteLine("C default constructor was called");
CVal = 0;
}
public C(int cv)
{
Console.WriteLine("C parameterized constructor was called");
CVal = cv;
}
private int cVal;
public int CVal
{
init
{
cVal = value;
Console.WriteLine($"C.cVal was initialized: {cVal}");
}
}
}

@ -0,0 +1,281 @@
using System.Collections;
using System.Linq.Expressions;
namespace KlipsLibrary;
public class Klips
{
public static void SayHello()
{
Console.WriteLine("Hello, C# library!");
}
public static void TestInput()
{
string formattingString = "Captured {0} input: {1}\n";
Console.Write("\nInput a character, then press enter: ");
int ascii = Console.Read();
char ch = Convert.ToChar(ascii);
Console.Write(formattingString, "character", ch);
Console.ReadLine(); // Discard any left over input
Console.Write("\nPress a key: ");
ConsoleKeyInfo key = Console.ReadKey();
Console.Write("\n" + formattingString, "key", key.KeyChar);
Console.Write("\nEnter a line: ");
string? line = Console.ReadLine();
Console.Write(formattingString, "line", line);
}
public static void PrintEnum<T>(IEnumerable<T> obj)
{
foreach (var i in obj)
{
Console.Write("{0}, ", i);
}
}
public static void PrintInfo<T>(IEnumerable<T> c)
{
Console.WriteLine("Type: {0}", c.GetType().ToString());
}
public static void Print<T>(IEnumerable<T> obj)
{
Console.WriteLine();
PrintInfo(obj);
PrintEnum(obj);
}
// Doesn't work because we can't resolve passed object name
// + Limited to parameter object name; ref causes errors
public static void PrintName<T>(T obj)
{
Expression<Func<object>> expression = () => obj!;
string name = ((expression.Body as MemberExpression)!).Member.Name;
Console.WriteLine("{0}", name);
}
public static void MakeGarbage(int count)
{
for (int i = 0; i < count; i++)
{
var v = new Version();
}
}
public static void TestContainers()
{
int[] test = { 1, 2, 3, 4, 5 };
Klips.Print(test);
var arr = new int[5];
for (int i = 1; i < 6; i++)
{
arr[i-1] = i;
}
Klips.Print(arr);
var list = new List<int>();
for (int i = 1; i < 6; i++)
{
list.Add(i);
}
Klips.Print(list);
list = list.Concat(arr).ToList();
Klips.Print(list);
list.Sort();
Klips.Print(list);
var dict = new Dictionary<int, string>()
{
[4] = "four",
[2] = "two",
[1] = "one",
[3] = "three",
[5] = "five",
};
Klips.Print(dict);
for (int i = 1; i <= 5; i++)
{
Console.Write("\n{0}", dict[i]);
}
var sortedDict = new SortedDictionary<int, string>(dict);
Klips.Print(sortedDict);
var hashset = new HashSet<int>{3, 1, 4, 2};
Klips.Print(hashset);
var sortedSet = new SortedSet<int>(hashset);
Klips.Print(sortedSet);
var sortedList = new SortedList(sortedDict);
Console.WriteLine("Type: {0}", sortedList.GetType().ToString());
foreach (DictionaryEntry item in sortedList)
{
Console.WriteLine("Key: {0} Value: {1}", item.Key.ToString(), item.Value);
}
// Klips.Print(sortedList);
var q = new Queue<string>(dict.Values);
Klips.Print(q);
var llist = new LinkedList<int>(dict.Keys);
Klips.Print(llist);
}
public static void TestGC()
{
Klips.MakeGarbage(1000000);
// GC.Collect();
Console.Write("\nHeap memory: {0}\nAllocated heap memory: {1}",
GC.GetGCMemoryInfo().HeapSizeBytes.ToString(), GC.GetTotalMemory(false).ToString());
for (int i = 0; i < 3; i++)
{
Console.Write("\nGeneration {0} collection count: {1}", i, GC.CollectionCount(i).ToString());
}
}
public static void TestStrings()
{
Console.Write("\n\nWhat time is it?\n{0}", DateTime.Now.ToString());
var lit = @"
hi
how
""are"" you? \this\is\a\literal
";
Console.WriteLine(lit);
string[] @foreach = {@"\this\is\new\a\test\n", "Not verbatim\nBut still literal"};
foreach (string s in @foreach)
{
Console.WriteLine(@s);
}
string a = "This is my string!";
Console.WriteLine($"This is my rifle; {a, 30}");
Console.WriteLine($"This is {{my}} rifle; {a, -30}");
var b = $"This {{is}} my rifle; {a}";
Console.WriteLine(b);
Console.WriteLine($"Conditional formatting result: {(b.Length == 0 ? "Empty" : "Not empty")}");
var pi = Math.PI;
Console.WriteLine($"{pi:F3}, {pi:F10}, {DateTime.Now:d}, {DateTime.Now:f}, {DateTime.Now.ToLocalTime():h:mm:ss tt zz}");
string fmt = "This is pi: {0}\nThis is the date: {1}\nThis is also pi: {0:F6}";
Console.WriteLine(fmt, Math.PI, DateTime.Now);
}
public static void TestLambdas()
{
// Both of these lambdas are of the same type; Func<string, int> where int is the value returned
var getLen = (string s) => s.Length;
Func<string, int> funcLen = (string s) => s.Length;
Console.WriteLine("Length: {0}", getLen("Hello").ToString());
Console.WriteLine("Length: {0}", funcLen("Hello").ToString());
var isEqual = (string a, string b) => a == b;
Console.WriteLine(isEqual("Test", "Test"));
Func<string, string, bool> funcIsEqual = (string a, string b) => a == b;
Console.WriteLine(funcIsEqual("Test", "Test"));
// These two lamdas are both of type Action<string>, as they do not return a result
var statement = (string s) =>
{
var arr = s.ToCharArray();
Array.Reverse(arr);
Console.WriteLine($"\"{s}\" reversed: {new string(arr)}");
};
Action<string> actionReverse = (string s) =>
{
var arr = s.ToCharArray();
Array.Reverse(arr);
Console.WriteLine($"\"{s}\" reversed: {new string(arr)}");
};
// This lamda is a Func<string, string> as it take a string parameter and returns a string as a result
Func<string, string> revString = (string s) =>
{
var revArr = s.ToCharArray();
Array.Reverse(revArr);
return new string(revArr);
};
string testS = "Racecar";
Console.WriteLine($"{testS} reversed: {revString(testS)}");
statement("Test");
}
public static void TestShape()
{
var shape = new Square();
shape.Print();
var shapeRef = shape;
shapeRef.Height = 20;
shape.Print();
var box = new List<Shape>();
box.Add(new Shape(5, 5));
box.Add(new Square());
box.Last().Width = 8; // Access the last element we added to the List, set its width to 8
box.Add(new Cube());
box.Add(new Rectangle());
box.Add(new Rect());
// Use a lambda to find a Cube, get a reference to it; If we found a Cube, set its depth to 5
if (box.Find((Shape s) => s.GetType() == typeof(Cube)) is Cube cubeRef) cubeRef.Depth = 5;
foreach (var s in box) s.Print(); // Print all the Shapes
var cub = new Cube();
var sqr = cub as Square;
if (sqr != null) sqr.Print();
Console.WriteLine("Testing upcast");
var c = new Cube();
c.Print();
if (c is Square cubeSquare)
{
// Why is Shape's Print() not called?; cubeShape.Print calls Square.Print() instead
var cubeShape = cubeSquare as Shape;
if (cubeShape != null) cubeShape.Print();
}
}
public static void TestBag()
{
var bag = new Bag();
Item wrench = new Item(1.5, 1, "wrench"); // Create a wrench using Item ctor
var spanner = wrench; // Copy wrench to a new item
spanner.Name = "spanner";
spanner.Value = 5.0;
spanner.Qty = 2;
Item socket = new Item(2.5, 5, "socket"); // Create a new item using ctor
bag.AddItem(wrench);
bag.AddItem(spanner);
bag.AddItem(socket);
Item? bagSpanner = bag.TakeItem(spanner);
Console.WriteLine(Object.ReferenceEquals(bagSpanner, spanner));
Item? noSpanner = bag.TakeItem(spanner);
Console.WriteLine(noSpanner == null);
}
public static void TestFruits()
{
Fruits fruits = new Fruits() { new Fruit(), new Fruit("Apple"), new Fruit("Orange")};
foreach (Fruit f in fruits)
{
Console.WriteLine(f.Name);
}
}
public static void TestInitOrder()
{
var aClass = new C(5) {CVal = 10};
}
}

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

@ -0,0 +1,98 @@
namespace KlipsLibrary;
public class Shape
{
public Shape(int y, int x)
{
Y = y;
X = x;
Name = this.ToString();
}
public Shape()
{
X = 0;
Y = 0;
Name = this.ToString();
}
// Shape position; Private setter, public getter
public int X { get; private set; }
public int Y { get; private set; }
public string Name { get; private set; }
// Auto-implemented properties may use a default value initializer
public virtual int Width { get; set; } = 1;
public virtual int Height { get; set; } = 2;
public virtual void Print()
{
Console.WriteLine($"{Name} WxH is {Width}x{Height} at position ({X},{Y})");
}
}
public class Square : Shape
{
// Set default value on encapsulated value for non auto-implemented properties
private int width = 10;
private int height = 10;
// We can override properties just as we can functions
// + Height and Width properties can no longer set default values
public override int Height
{
// Can use expressions for getters / setters
get => height;
set => width = height = value;
}
public override int Width
{
get => width;
set
{
// Same setter as Height, just within a block of statements
width = value;
height = value;
}
}
public override void Print()
{
Console.WriteLine("Printing Square info...");
base.Print(); // Will use Square's getter / setter to print private int width, height
}
}
public class Cube : Square
{
// Add new properties or encapsulated values as needed
private int depth = 10;
public int Depth
{
get => depth;
set => depth = value;
}
// Implement a `new` Print() function which acts as a new stand-alone implementaton
public new void Print()
{
Console.WriteLine("Printing Cube info...");
Console.WriteLine($"{Name} WxHxD is {Width}x{Height}x{Depth} at position ({X},{Y})");
}
}
public class Rectangle : Shape
{
// Classes that inherit from Rectangle can not override Print
public sealed override void Print()
{
Console.WriteLine("Printing sealed Rectangle info...");
base.Print();
}
}
public class Rect : Rectangle
{
// Rect can't override Print(), since its base class declared it as `sealed`
}

@ -0,0 +1,5 @@
This is a testing project I created while first learning C#.
There's no objective or goal, aside from playing with different features of C# and NuGet packages.
Essentially, this is a scrap project that I code in while learning new C# things.
Since this is just for learning, I won't bother explaining how to use things here; It's very possible this entire project could disappear one day.

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KlipsLibrary", "KlipsLibrary\KlipsLibrary.csproj", "{58CB87C5-7D98-43F9-8AD8-C73766C06E51}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KlipsLibrary.Test", "KlipsLibrary.Test\KlipsLibrary.Test.csproj", "{3576A541-1B1E-42A1-A348-B0CAA3B5BC5A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KlipsConsole", "KlipsConsole\KlipsConsole.csproj", "{A1E88D77-4A17-47BF-BED4-CEB1821FB627}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{58CB87C5-7D98-43F9-8AD8-C73766C06E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58CB87C5-7D98-43F9-8AD8-C73766C06E51}.Debug|Any CPU.Build.0 = Debug|Any CPU
{58CB87C5-7D98-43F9-8AD8-C73766C06E51}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58CB87C5-7D98-43F9-8AD8-C73766C06E51}.Release|Any CPU.Build.0 = Release|Any CPU
{3576A541-1B1E-42A1-A348-B0CAA3B5BC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3576A541-1B1E-42A1-A348-B0CAA3B5BC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3576A541-1B1E-42A1-A348-B0CAA3B5BC5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3576A541-1B1E-42A1-A348-B0CAA3B5BC5A}.Release|Any CPU.Build.0 = Release|Any CPU
{A1E88D77-4A17-47BF-BED4-CEB1821FB627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1E88D77-4A17-47BF-BED4-CEB1821FB627}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1E88D77-4A17-47BF-BED4-CEB1821FB627}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1E88D77-4A17-47BF-BED4-CEB1821FB627}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Loading…
Cancel
Save