diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000..2b5f541
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,30 @@
+#---------------------------------#
+# Build Image #
+#---------------------------------#
+image: Visual Studio 2017
+
+#---------------------------------#
+# Build Script #
+#---------------------------------#
+build_script:
+ - ps: .\build.ps1 -Target AppVeyor
+
+# Tests
+test: off
+
+#---------------------------------#
+# Branches to build #
+#---------------------------------#
+branches:
+ # Whitelist
+ only:
+ - develop
+ - master
+ - /release/.*/
+ - /hotfix/.*/
+
+#---------------------------------#
+# Build Cache #
+#---------------------------------#
+cache:
+- tools -> setup.cake
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..c398278
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,3 @@
+# These owners will be the default owners for everything in the repo and
+# will be requested for review when someone opens a pull request.
+* @Speeedy01 @marco-bertschi @pascalberger @christianbumann @x-jokay @silanosa @georgesgoetz
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3e759b7..d286e5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -299,8 +299,8 @@ __pycache__/
*.pyc
# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
+tools/**
+!tools/packages.config
# Tabs Studio
*.tss
@@ -328,3 +328,8 @@ ASALocalRun/
# MFractors (Xamarin productivity tool) working folder
.mfractor/
+
+# Project specific
+
+config.wyam.*
+BuildArtifacts/
\ No newline at end of file
diff --git a/.mergify.yml b/.mergify.yml
new file mode 100644
index 0000000..8c38b80
--- /dev/null
+++ b/.mergify.yml
@@ -0,0 +1,5 @@
+pull_request_rules:
+ - name: delete head branch after merge
+ conditions: []
+ actions:
+ delete_head_branch: {}
\ No newline at end of file
diff --git a/GitReleaseManager.yaml b/GitReleaseManager.yaml
new file mode 100644
index 0000000..721c1ba
--- /dev/null
+++ b/GitReleaseManager.yaml
@@ -0,0 +1,12 @@
+issue-labels-include:
+- Breaking change
+- Feature
+- Bug
+- Improvement
+- Documentation
+issue-labels-exclude:
+- Build
+issue-labels-alias:
+ - name: Documentation
+ header: Documentation
+ plural: Documentation
\ No newline at end of file
diff --git a/README.md b/README.md
index 4911065..a221a7c 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,36 @@
-# BBT.Strategy
-A strategy pattern implementation
+# BBT.StrategyPattern
+
+An strategy pattern implementation for .NET.
+
+[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/bbtsoftware/BBT.StrategyPattern/blob/master/LICENSE)
+
+## Information
+
+| | Stable | Pre-release |
+|:--:|:--:|:--:|
+|GitHub Release|-|[![GitHub release](https://img.shields.io/github/release/bbtsoftware/BBT.StrategyPattern.svg)](https://github.com/bbtsoftware/BBT.StrategyPattern/releases/latest)|
+|NuGet|[![NuGet](https://img.shields.io/nuget/v/BBT.StrategyPattern.svg)](https://www.nuget.org/packages/BBT.StrategyPattern)|[![NuGet](https://img.shields.io/nuget/vpre/BBT.StrategyPattern.svg)](https://www.nuget.org/packages/BBT.StrategyPattern)|
+
+## Build Status
+
+|Develop|Master|
+|:--:|:--:|
+|[![Build status](https://ci.appveyor.com/api/projects/status/bncb5oc7ah2ti95y/branch/develop?svg=true)](https://ci.appveyor.com/project/BBTSoftwareAG/bbt-strategypattern/branch/develop)|[![Build status](https://ci.appveyor.com/api/projects/status/bncb5oc7ah2ti95y/branch/master?svg=true)](https://ci.appveyor.com/project/BBTSoftwareAG/bbt-strategypattern/branch/master)|
+
+## Code Coverage
+
+[![Coverage Status](https://coveralls.io/repos/github/bbtsoftware/BBT.StrategyPattern/badge.svg?branch=develop)](https://coveralls.io/github/bbtsoftware/BBT.StrategyPattern?branch=develop)
+
+## Quick Links
+
+* [Documentation](https://bbtsoftware.github.io/BBT.StrategyPattern/)
+
+## Build
+
+To build this package we are using [Cake](https://cakebuild.net).
+
+On Windows PowerShell run:
+
+```powershell
+./build
+```
diff --git a/build.ps1 b/build.ps1
new file mode 100644
index 0000000..bdfb32b
--- /dev/null
+++ b/build.ps1
@@ -0,0 +1,184 @@
+##########################################################################
+# This is the Cake bootstrapper script for PowerShell.
+# This file was downloaded from https://github.com/cake-build/resources
+# Feel free to change this file to fit your needs.
+##########################################################################
+
+<#
+.SYNOPSIS
+This is a Powershell script to bootstrap a Cake build.
+.DESCRIPTION
+This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
+and execute your Cake build script with the parameters you provide.
+.PARAMETER Script
+The build script to execute.
+.PARAMETER Target
+The build script target to run.
+.PARAMETER Configuration
+The build configuration to use.
+.PARAMETER Verbosity
+Specifies the amount of information to be displayed.
+.PARAMETER Experimental
+Tells Cake to use the latest Roslyn release.
+.PARAMETER WhatIf
+Performs a dry run of the build script.
+No tasks will be executed.
+.PARAMETER Mono
+Tells Cake to use the Mono scripting engine.
+.PARAMETER SkipToolPackageRestore
+Skips restoring of packages.
+.PARAMETER ScriptArgs
+Remaining arguments are added here.
+.LINK
+http://cakebuild.net
+#>
+
+[CmdletBinding()]
+Param(
+ [string]$Script = "setup.cake",
+ [string]$Target = "Default",
+ [ValidateSet("Release", "Debug")]
+ [string]$Configuration = "Release",
+ [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
+ [string]$Verbosity = "Verbose",
+ [switch]$Experimental,
+ [Alias("DryRun","Noop")]
+ [switch]$WhatIf,
+ [switch]$Mono,
+ [switch]$SkipToolPackageRestore,
+ [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
+ [string[]]$ScriptArgs
+)
+
+[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
+function MD5HashFile([string] $filePath)
+{
+ if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
+ {
+ return $null
+ }
+
+ [System.IO.Stream] $file = $null;
+ [System.Security.Cryptography.MD5] $md5 = $null;
+ try
+ {
+ $md5 = [System.Security.Cryptography.MD5]::Create()
+ $file = [System.IO.File]::OpenRead($filePath)
+ return [System.BitConverter]::ToString($md5.ComputeHash($file))
+ }
+ finally
+ {
+ if ($file -ne $null)
+ {
+ $file.Dispose()
+ }
+ }
+}
+
+Write-Host "Preparing to run build script..."
+
+if(!$PSScriptRoot){
+ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
+}
+
+$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
+$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
+$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
+$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
+$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
+$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
+
+# Should we use mono?
+$UseMono = "";
+if($Mono.IsPresent) {
+ Write-Verbose -Message "Using the Mono based scripting engine."
+ $UseMono = "-mono"
+}
+
+# Should we use the new Roslyn?
+$UseExperimental = "";
+if($Experimental.IsPresent -and !($Mono.IsPresent)) {
+ Write-Verbose -Message "Using experimental version of Roslyn."
+ $UseExperimental = "-experimental"
+}
+
+# Is this a dry run?
+$UseDryRun = "";
+if($WhatIf.IsPresent) {
+ $UseDryRun = "-dryrun"
+}
+
+# Make sure tools folder exists
+if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
+ Write-Verbose -Message "Creating tools directory..."
+ New-Item -Path $TOOLS_DIR -Type directory | out-null
+}
+
+# Make sure that packages.config exist.
+if (!(Test-Path $PACKAGES_CONFIG)) {
+ Write-Verbose -Message "Downloading packages.config..."
+ try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
+ Throw "Could not download packages.config."
+ }
+}
+
+# Try find NuGet.exe in path if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Trying to find nuget.exe in PATH..."
+ $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
+ $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
+ if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
+ Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
+ $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
+ }
+}
+
+# Try download NuGet.exe if not exists
+if (!(Test-Path $NUGET_EXE)) {
+ Write-Verbose -Message "Downloading NuGet.exe..."
+ try {
+ (New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
+ } catch {
+ Throw "Could not download NuGet.exe."
+ }
+}
+
+# Save nuget.exe path to environment to be available to child processed
+$ENV:NUGET_EXE = $NUGET_EXE
+
+# Restore tools from NuGet?
+if(-Not $SkipToolPackageRestore.IsPresent) {
+ Push-Location
+ Set-Location $TOOLS_DIR
+
+ # Check for changes in packages.config and remove installed tools if true.
+ [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
+ if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
+ ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
+ Write-Verbose -Message "Missing or changed package.config hash..."
+ Remove-Item * -Recurse -Exclude packages.config,nuget.exe
+ }
+
+ Write-Verbose -Message "Restoring tools from NuGet..."
+ $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -PreRelease -OutputDirectory `"$TOOLS_DIR`" -Source https://www.myget.org/F/cake/api/v3/index.json"
+
+ if ($LASTEXITCODE -ne 0) {
+ Throw "An error occured while restoring NuGet tools."
+ }
+ else
+ {
+ $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
+ }
+ Write-Verbose -Message ($NuGetOutput | out-string)
+ Pop-Location
+}
+
+# Make sure that Cake has been installed.
+if (!(Test-Path $CAKE_EXE)) {
+ Throw "Could not find Cake.exe at $CAKE_EXE"
+}
+
+# Start Cake
+Write-Host "Running build script..."
+Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
+exit $LASTEXITCODE
\ No newline at end of file
diff --git a/docs/input/_Bottom.cshtml b/docs/input/_Bottom.cshtml
new file mode 100644
index 0000000..5b3d2af
--- /dev/null
+++ b/docs/input/_Bottom.cshtml
@@ -0,0 +1,50 @@
+
+
+
+
+
diff --git a/docs/input/_Footer.cshtml b/docs/input/_Footer.cshtml
new file mode 100644
index 0000000..4ad5bce
--- /dev/null
+++ b/docs/input/_Footer.cshtml
@@ -0,0 +1,5 @@
+
+ Copyright © BBT Software AG and contributors .
+
+ Website generated by Wyam
+
diff --git a/docs/input/_Navbar.cshtml b/docs/input/_Navbar.cshtml
new file mode 100644
index 0000000..0a7d28d
--- /dev/null
+++ b/docs/input/_Navbar.cshtml
@@ -0,0 +1,12 @@
+@{
+ List> pages = new List>
+ {
+ Tuple.Create("Documentation", Context.GetLink("docs")),
+ Tuple.Create("API", Context.GetLink("api/BBT.StrategyPattern"))
+ };
+ foreach(Tuple p in pages)
+ {
+ string active = Context.GetLink(Document).StartsWith(p.Item2) ? "active" : null;
+ @Html.Raw(p.Item1)
+ }
+}
\ No newline at end of file
diff --git a/docs/input/assets/css/fonts/glyphicons-halflings-regular.eot b/docs/input/assets/css/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..b93a495
Binary files /dev/null and b/docs/input/assets/css/fonts/glyphicons-halflings-regular.eot differ
diff --git a/docs/input/assets/css/fonts/glyphicons-halflings-regular.svg b/docs/input/assets/css/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..94fb549
--- /dev/null
+++ b/docs/input/assets/css/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/input/assets/css/fonts/glyphicons-halflings-regular.ttf b/docs/input/assets/css/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..1413fc6
Binary files /dev/null and b/docs/input/assets/css/fonts/glyphicons-halflings-regular.ttf differ
diff --git a/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff b/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..9e61285
Binary files /dev/null and b/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff differ
diff --git a/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff2 b/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
Binary files /dev/null and b/docs/input/assets/css/fonts/glyphicons-halflings-regular.woff2 differ
diff --git a/docs/input/assets/css/override.less b/docs/input/assets/css/override.less
new file mode 100644
index 0000000..3208c66
--- /dev/null
+++ b/docs/input/assets/css/override.less
@@ -0,0 +1,139 @@
+/* Control the margin for bootstrap alert boxes */
+.alert > p {
+ margin-top: 0px;
+}
+
+/* Control the look and feel of the copy box applied to code sections */
+.btn-copy[disabled] .clippy {
+ opacity: .3;
+}
+pre .btn-copy {
+ -webkit-transition: opacity 0.3s ease-in-out;
+ -o-transition: opacity 0.3s ease-in-out;
+ transition: opacity 0.3s ease-in-out;
+ opacity: 0;
+ padding: 2px 6px;
+ float: right;
+}
+pre:hover .btn-copy {
+ opacity: 1;
+}
+.tooltipped {
+ position: relative
+}
+.tooltipped:after {
+ position: absolute;
+ z-index: 1000000;
+ display: none;
+ padding: 5px 8px;
+ font: normal normal 11px/1.5 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
+ color: #fff;
+ text-align: center;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-wrap: break-word;
+ white-space: pre;
+ pointer-events: none;
+ content: attr(aria-label);
+ background: rgba(0, 0, 0, 0.8);
+ border-radius: 3px;
+ -webkit-font-smoothing: subpixel-antialiased
+}
+.tooltipped:before {
+ position: absolute;
+ z-index: 1000001;
+ display: none;
+ width: 0;
+ height: 0;
+ color: rgba(0, 0, 0, 0.8);
+ pointer-events: none;
+ content: "";
+ border: 5px solid transparent
+}
+.tooltipped:hover:before, .tooltipped:hover:after, .tooltipped:active:before, .tooltipped:active:after, .tooltipped:focus:before, .tooltipped:focus:after {
+ display: inline-block;
+ text-decoration: none
+}
+.tooltipped-s:after, .tooltipped-se:after, .tooltipped-sw:after {
+ top: 100%;
+ right: 50%;
+ margin-top: 5px
+}
+.tooltipped-s:before, .tooltipped-se:before, .tooltipped-sw:before {
+ top: auto;
+ right: 50%;
+ bottom: -5px;
+ margin-right: -5px;
+ border-bottom-color: rgba(0, 0, 0, 0.8)
+}
+
+@font-family-sans-serif: "Roboto", Helvetica, Arial, sans-serif;
+
+/* For Gitter and GitHub */
+.bottom-footer {
+ margin-bottom: 40px !important; // Make room for Gitter and GitHub buttons
+}
+
+.gitter-open-chat-button {
+ background-color: #3c8dbc;
+ font-family: @font-family-sans-serif;
+ letter-spacing: normal;
+ right: 90px;
+}
+
+.gitter-open-chat-button:focus, .gitter-open-chat-button:hover,
+.github-button:focus, .github-button:hover,
+{
+ background-color: #4EABDD;
+ color: #fff;
+}
+
+.gitter-chat-embed {
+ top: 49px;
+ border-top: 1px solid #000;
+ z-index: 10000;
+}
+
+.github-button {
+ z-index: 100;
+ position: fixed;
+ bottom: 0px;
+ right: 240px;
+ padding: 1em 3em;
+ background-color: #367fa9;
+ border: 0;
+ border-top-left-radius: 0.5em;
+ border-top-right-radius: 0.5em;
+ font-family: sans-serif;
+ font-size: 9pt;
+ text-transform: uppercase;
+ text-align: center;
+ text-decoration: none;
+ cursor: pointer;
+ cursor: hand;
+ -webkit-transition: all .3s ease;
+ transition: all .3s ease;
+ color: #fff;
+ a, a:active, a:hover, a:focus {
+ color: #fff;
+ }
+}
+
+/* For feature list */
+
+.feature-list li {
+ display: block;
+}
+
+.feature-list li:before {
+ /*Using a Bootstrap glyphicon as the bullet point*/
+ content: "\e013";
+ font-family: 'Glyphicons Halflings';
+ font-size: 12px;
+ float: left;
+ margin-top: 1px;
+ margin-left: -25px;
+ color: green;
+}
\ No newline at end of file
diff --git a/docs/input/assets/images/clippy.svg b/docs/input/assets/images/clippy.svg
new file mode 100644
index 0000000..e1b1703
--- /dev/null
+++ b/docs/input/assets/images/clippy.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/docs/input/assets/js/anchor.min.js b/docs/input/assets/js/anchor.min.js
new file mode 100644
index 0000000..7f34489
--- /dev/null
+++ b/docs/input/assets/js/anchor.min.js
@@ -0,0 +1,6 @@
+/**
+ * AnchorJS - v3.2.2 - 2016-10-05
+ * https://github.com/bryanbraun/anchorjs
+ * Copyright (c) 2016 Bryan Braun; Licensed MIT
+ */
+!function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";function A(A){function e(A){A.icon=A.hasOwnProperty("icon")?A.icon:"",A.visible=A.hasOwnProperty("visible")?A.visible:"hover",A.placement=A.hasOwnProperty("placement")?A.placement:"right",A.class=A.hasOwnProperty("class")?A.class:"",A.truncate=A.hasOwnProperty("truncate")?Math.floor(A.truncate):64}function t(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new Error("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}function n(){if(null===document.head.querySelector("style.anchorjs")){var A,e=document.createElement("style"),t=" .anchorjs-link { opacity: 0; text-decoration: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }",n=" *:hover > .anchorjs-link, .anchorjs-link:focus { opacity: 1; }",i=' @font-face { font-family: "anchorjs-icons"; src: url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype"); }',o=" [data-anchorjs-icon]::after { content: attr(data-anchorjs-icon); }";e.className="anchorjs",e.appendChild(document.createTextNode("")),A=document.head.querySelector('[rel="stylesheet"], style'),void 0===A?document.head.appendChild(e):document.head.insertBefore(e,A),e.sheet.insertRule(t,e.sheet.cssRules.length),e.sheet.insertRule(n,e.sheet.cssRules.length),e.sheet.insertRule(o,e.sheet.cssRules.length),e.sheet.insertRule(i,e.sheet.cssRules.length)}}this.options=A||{},this.elements=[],e(this.options),this.isTouchDevice=function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var i,o,s,c,r,a,h,l,u,d,f,p,w=[];if(e(this.options),p=this.options.visible,"touch"===p&&(p=this.isTouchDevice()?"always":"hover"),A||(A="h1, h2, h3, h4, h5, h6"),i=t(A),0===i.length)return!1;for(n(),o=document.querySelectorAll("[id]"),s=[].map.call(o,function(A){return A.id}),r=0;r-1,t=A.lastChild&&(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ")>-1;return e||t||!1}}return A});
diff --git a/docs/input/assets/js/clipboard.min.js b/docs/input/assets/js/clipboard.min.js
new file mode 100644
index 0000000..1d7c5d5
--- /dev/null
+++ b/docs/input/assets/js/clipboard.min.js
@@ -0,0 +1,7 @@
+/*!
+ * clipboard.js v1.5.16
+ * https://zenorocha.github.io/clipboard.js
+ *
+ * Licensed MIT © Zeno Rocha
+ */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Clipboard=e()}}(function(){var e,t,n;return function e(t,n,i){function o(a,c){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var s=new Error("Cannot find module '"+a+"'");throw s.code="MODULE_NOT_FOUND",s}var u=n[a]={exports:{}};t[a][0].call(u.exports,function(e){var n=t[a][1][e];return o(n?n:e)},u,u.exports,e,t,n,i)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function e(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function e(){var t=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var i=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.addEventListener("focus",window.scrollTo(0,i)),this.fakeElem.style.top=i+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,o.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function e(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function e(){this.selectedText=(0,o.default)(this.target),this.copyText()}},{key:"copyText",value:function e(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function e(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function e(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function e(){this.removeFake()}},{key:"action",set:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function e(){return this._action}},{key:"target",set:function e(t){if(void 0!==t){if(!t||"object"!==("undefined"==typeof t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function e(){return this._target}}]),e}();e.exports=c})},{select:5}],8:[function(t,n,i){!function(o,r){if("function"==typeof e&&e.amd)e(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof i)r(n,t("./clipboard-action"),t("tiny-emitter"),t("good-listener"));else{var a={exports:{}};r(a,o.clipboardAction,o.tinyEmitter,o.goodListener),o.clipboard=a.exports}}(this,function(e,t,n,i){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}var s=o(t),u=o(n),f=o(i),d=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText}},{key:"listenClick",value:function e(t){var n=this;this.listener=(0,f.default)(t,"click",function(e){return n.onClick(e)})}},{key:"onClick",value:function e(t){var n=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new s.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})}},{key:"defaultAction",value:function e(t){return l("action",t)}},{key:"defaultTarget",value:function e(t){var n=l("target",t);if(n)return document.querySelector(n)}},{key:"defaultText",value:function e(t){return l("text",t)}},{key:"destroy",value:function e(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}]),t}(u.default);e.exports=h})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)});
\ No newline at end of file
diff --git a/docs/input/docs/features.md b/docs/input/docs/features.md
new file mode 100644
index 0000000..5356bdc
--- /dev/null
+++ b/docs/input/docs/features.md
@@ -0,0 +1,11 @@
+---
+Order: 10
+Title: Features
+Description: Feature overview of BBT.StrategyPattern.
+---
+
+
+ Fully abstract
+ Works with any IoC framework
+ Instance creator with IoC
+
diff --git a/docs/input/docs/index.cshtml b/docs/input/docs/index.cshtml
new file mode 100644
index 0000000..0610eb5
--- /dev/null
+++ b/docs/input/docs/index.cshtml
@@ -0,0 +1,13 @@
+---
+Title: Documentation
+---
+@foreach(IDocument child in Model.DocumentList(Keys.Children).OrderBy(x => x.Get(DocsKeys.Order, 1000)))
+{
+ @(child.String(Keys.Title))
+ if(child.ContainsKey(DocsKeys.Description))
+ {
+ @Html.Raw(child.String(DocsKeys.Description))
+ }
+
+ @Html.Partial("_ChildPages", child)
+}
\ No newline at end of file
diff --git a/docs/input/docs/usage/index.cshtml b/docs/input/docs/usage/index.cshtml
new file mode 100644
index 0000000..ed3e2cc
--- /dev/null
+++ b/docs/input/docs/usage/index.cshtml
@@ -0,0 +1,7 @@
+---
+Order: 20
+Description: How to obtain, configure, and use BBT.StrategyPattern.
+---
+@Html.Raw(Model.String(DocsKeys.Description))
+
+@Html.Partial("_ChildPages")
\ No newline at end of file
diff --git a/docs/input/docs/usage/use-with-ioc.md b/docs/input/docs/usage/use-with-ioc.md
new file mode 100644
index 0000000..f606231
--- /dev/null
+++ b/docs/input/docs/usage/use-with-ioc.md
@@ -0,0 +1,38 @@
+---
+Order: 20
+Title: Use with IoC
+Description: Example how to use BBT.StrategyPattern with IoC.
+---
+
+```csharp
+public void WorksWithIocNinject()
+{
+ var calc1 = new CalculationInput() { Number1 = 5, Number2 = 3 };
+ var op1 = new Operator() { Operation = OperatorEnum.Addition };
+ var op2 = new Operator() { Operation = OperatorEnum.Subtraktion };
+
+ IKernel kernel = new StandardKernel();
+
+ kernel
+ .Bind>()
+ .ToMethod((con) => new NinjectStrategyLocator(kernel));
+
+ kernel
+ .Bind()
+ .To();
+ kernel
+ .Bind()
+ .To();
+ kernel
+ .Bind>()
+ .To>();
+
+ IOperatorStrategy strategy;
+
+ strategy = kernel.Get>().GetStrategy(op1);
+ strategy.DoCalculate(calc1).Should().Be(8);
+
+ strategy = kernel.Get>().GetStrategy(op2);
+ strategy.DoCalculate(calc1).Should().Be(2);
+}
+```
diff --git a/docs/input/docs/usage/use-without-ioc.md b/docs/input/docs/usage/use-without-ioc.md
new file mode 100644
index 0000000..2a7fc8a
--- /dev/null
+++ b/docs/input/docs/usage/use-without-ioc.md
@@ -0,0 +1,25 @@
+---
+Order: 10
+Title: Use without IoC
+Description: Example how to use BBT.StrategyPattern without IoC.
+---
+
+```csharp
+public void GenericStrategyWorksInMemory()
+{
+ var calc1 = new CalculationInput() { Number1 = 5, Number2 = 3 };
+ var op1 = new Operator() { Operation = OperatorEnum.Addition };
+ var op2 = new Operator() { Operation = OperatorEnum.Subtraktion };
+
+ var factory = new MemoryOperatorStrategyLocator();
+ var strategyProvider = new GenericStrategyProvider(factory);
+
+ IOperatorStrategy strategy;
+
+ strategy = strategyProvider.GetStrategy(op1);
+ strategy.DoCalculate(calc1).Should().Be(8);
+
+ strategy = strategyProvider.GetStrategy(op2);
+ strategy.DoCalculate(calc1).Should().Be(2);
+}
+```
diff --git a/docs/input/index.cshtml b/docs/input/index.cshtml
new file mode 100644
index 0000000..4352bae
--- /dev/null
+++ b/docs/input/index.cshtml
@@ -0,0 +1,36 @@
+---
+Title: BBT.StrategyPattern
+NoSidebar: true
+NoContainer: true
+NoGutter: true
+---
+
+
+
+
+
+
+
+
+
+
+
+ BBT.StrategyPattern a strategy pattern implementation for .NET.
+
+
+
Resources about strategy pattern
+
+
+
\ No newline at end of file
diff --git a/docs/packages.xml b/docs/packages.xml
new file mode 100644
index 0000000..d85bac4
--- /dev/null
+++ b/docs/packages.xml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/nuspec/nuget/BBT.StrategyPattern.nuspec b/nuspec/nuget/BBT.StrategyPattern.nuspec
new file mode 100644
index 0000000..24a9816
--- /dev/null
+++ b/nuspec/nuget/BBT.StrategyPattern.nuspec
@@ -0,0 +1,25 @@
+
+
+
+ BBT.StrategyPattern
+ BBT StrategyPattern
+ 0.0.0
+ BBT Software AG
+ bbtsoftware
+ A strategy pattern implementation for .NET.
+ A strategy pattern implementation for .NET.
+ MIT
+ https://github.com/bbtsoftware/BBT.StrategyPattern/
+ https://raw.githubusercontent.com/bbtsoftware/BBT.StrategyPattern/dfa1b06283f8e4d7dbd3793a3a4c2be7e2cff0c9/nuspec/nuget/icon.png
+ false
+
+ Copyright © BBT Software AG
+ Strategy Pattern
+ https://github.com/bbtsoftware/BBT.StrategyPattern/releases/tag/1.0.0
+
+
+
+
+
+
+
diff --git a/nuspec/nuget/icon.png b/nuspec/nuget/icon.png
new file mode 100644
index 0000000..9925180
Binary files /dev/null and b/nuspec/nuget/icon.png differ
diff --git a/setup.cake b/setup.cake
new file mode 100644
index 0000000..4c01b0c
--- /dev/null
+++ b/setup.cake
@@ -0,0 +1,34 @@
+#load nuget:?package=Cake.Recipe&version=1.0.0
+
+//////////////////////////////////////////////////////////////////////
+// PARAMETERS
+//////////////////////////////////////////////////////////////////////
+
+Environment.SetVariableNames();
+
+BuildParameters.SetParameters(
+ context: Context,
+ buildSystem: BuildSystem,
+ sourceDirectoryPath: "./src",
+ title: "BBT.StrategyPattern",
+ repositoryOwner: "bbtsoftware",
+ repositoryName: "BBT.StrategyPattern",
+ appVeyorAccountName: "BBTSoftwareAG",
+ shouldPublishMyGet: false,
+ shouldRunCodecov: true,
+ shouldDeployGraphDocumentation: false);
+
+BuildParameters.PrintParameters(Context);
+
+ToolSettings.SetToolSettings(
+ context: Context,
+ dupFinderExcludePattern: new string[] { BuildParameters.RootDirectoryPath + "/src/BBT.StrategyPattern.Tests/*.cs" },
+ testCoverageFilter: "+[*]* -[xunit.*]* -[*.Tests]* -[FluentAssertions]*",
+ testCoverageExcludeByAttribute: "*.ExcludeFromCodeCoverage*",
+ testCoverageExcludeByFile: "*/*Designer.cs;*/*.g.cs;*/*.g.i.cs");
+
+//////////////////////////////////////////////////////////////////////
+// EXECUTION
+//////////////////////////////////////////////////////////////////////
+
+Build.RunDotNetCore();
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern.Tests.ruleset b/src/BBT.StrategyPattern.Tests.ruleset
new file mode 100644
index 0000000..3f69a17
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests.ruleset
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern.Tests/BBT.StrategyPattern.Tests.csproj b/src/BBT.StrategyPattern.Tests/BBT.StrategyPattern.Tests.csproj
new file mode 100644
index 0000000..fe3e9e6
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/BBT.StrategyPattern.Tests.csproj
@@ -0,0 +1,42 @@
+
+
+
+ netcoreapp2.1
+ false
+ BBT.StrategyPattern.Tests
+ BBT Software AG
+ BBT.StrategyPattern
+ Tests for BBT.StrategyPattern
+ Copyright © BBT Software AG
+ ..\BBT.StrategyPattern.Tests.ruleset
+ bin\$(Configuration)\
+
+
+
+ full
+
+
+ pdbonly
+
+
+
+
+
+
+
+
+ all
+
+
+
+
+
+
+
+
+
+ System
+
+
+
+
diff --git a/src/BBT.StrategyPattern.Tests/Data/CalculationInput.cs b/src/BBT.StrategyPattern.Tests/Data/CalculationInput.cs
new file mode 100644
index 0000000..d31de2b
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/Data/CalculationInput.cs
@@ -0,0 +1,12 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.Data
+{
+ public class CalculationInput
+ {
+ public double Number1 { get; set; }
+
+ public double Number2 { get; set; }
+
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/Data/Operator.cs b/src/BBT.StrategyPattern.Tests/Data/Operator.cs
new file mode 100644
index 0000000..4a05439
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/Data/Operator.cs
@@ -0,0 +1,9 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.Data
+{
+ public class Operator
+ {
+ public OperatorEnum Operation { get; set; }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/Data/OperatorEnum.cs b/src/BBT.StrategyPattern.Tests/Data/OperatorEnum.cs
new file mode 100644
index 0000000..0d92e36
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/Data/OperatorEnum.cs
@@ -0,0 +1,11 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.Data
+{
+ public enum OperatorEnum
+ {
+ None = 0,
+ Addition = 1,
+ Subtraktion = 2,
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/AdditionStrategy.cs b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/AdditionStrategy.cs
new file mode 100644
index 0000000..62176b8
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/AdditionStrategy.cs
@@ -0,0 +1,22 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.ExampleStrategyImpl
+{
+ using BBT.StrategyPattern.Tests.Data;
+ using FluentAssertions;
+
+ public class AdditionStrategy : IOperatorStrategy
+ {
+ public double DoCalculate(CalculationInput calc)
+ {
+ return calc.Number1 + calc.Number2;
+ }
+
+ public bool IsResponsible(Operator criterion)
+ {
+ criterion.Should().NotBeNull();
+
+ return criterion.Operation == OperatorEnum.Addition;
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/IOperatorStrategy.cs b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/IOperatorStrategy.cs
new file mode 100644
index 0000000..5707b8d
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/IOperatorStrategy.cs
@@ -0,0 +1,11 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.ExampleStrategyImpl
+{
+ using BBT.StrategyPattern.Tests.Data;
+
+ public interface IOperatorStrategy : IGenericStrategy
+ {
+ double DoCalculate(CalculationInput calc);
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/SubstractionStrategy.cs b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/SubstractionStrategy.cs
new file mode 100644
index 0000000..e4103ed
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/ExampleStrategyImpl/SubstractionStrategy.cs
@@ -0,0 +1,22 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.ExampleStrategyImpl
+{
+ using BBT.StrategyPattern.Tests.Data;
+ using FluentAssertions;
+
+ public class SubstractionStrategy : IOperatorStrategy
+ {
+ public double DoCalculate(CalculationInput calc)
+ {
+ return calc.Number1 - calc.Number2;
+ }
+
+ public bool IsResponsible(Operator criterion)
+ {
+ criterion.Should().NotBeNull();
+
+ return criterion.Operation == OperatorEnum.Subtraktion;
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/WithIoc/NinjectStrategyLocator.cs b/src/BBT.StrategyPattern.Tests/WithIoc/NinjectStrategyLocator.cs
new file mode 100644
index 0000000..e221e48
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/WithIoc/NinjectStrategyLocator.cs
@@ -0,0 +1,23 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.WithIoc
+{
+ using System;
+ using System.Collections.Generic;
+ using Ninject;
+
+ public class NinjectStrategyLocator : IStrategyLocator
+ {
+ public NinjectStrategyLocator(IKernel kernel)
+ {
+ this.Kernel = kernel ?? throw new ArgumentNullException(nameof(kernel));
+ }
+
+ public IKernel Kernel { get; }
+
+ public IEnumerable GetAllStrategies()
+ {
+ return Kernel.GetAll();
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/WithIocTest.cs b/src/BBT.StrategyPattern.Tests/WithIocTest.cs
new file mode 100644
index 0000000..bd3cf65
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/WithIocTest.cs
@@ -0,0 +1,43 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests
+{
+ using BBT.StrategyPattern.Tests.Data;
+ using BBT.StrategyPattern.Tests.ExampleStrategyImpl;
+ using BBT.StrategyPattern.Tests.WithIoc;
+ using FluentAssertions;
+ using Ninject;
+ using Xunit;
+
+ public class WithIocTest
+ {
+ [Fact]
+ public void WorksWithIocNinject()
+ {
+ // Prepare data
+ var calc1 = new CalculationInput() { Number1 = 5, Number2 = 3 };
+ var op1 = new Operator() { Operation = OperatorEnum.Addition };
+ var op2 = new Operator() { Operation = OperatorEnum.Subtraktion };
+
+
+ // IoC registrations
+ IKernel kernel = new StandardKernel();
+
+ kernel.Bind>().ToMethod((con) => new NinjectStrategyLocator(kernel));
+
+ kernel.Bind().To();
+ kernel.Bind().To();
+
+ kernel.Bind>().To>();
+
+ // Use strategy
+ IOperatorStrategy strategy;
+
+ strategy = kernel.Get>().GetStrategy(op1);
+ strategy.DoCalculate(calc1).Should().Be(8);
+
+ strategy = kernel.Get>().GetStrategy(op2);
+ strategy.DoCalculate(calc1).Should().Be(2);
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/WithoutIoc/MemoryOperatorStrategyLocator.cs b/src/BBT.StrategyPattern.Tests/WithoutIoc/MemoryOperatorStrategyLocator.cs
new file mode 100644
index 0000000..d224c3e
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/WithoutIoc/MemoryOperatorStrategyLocator.cs
@@ -0,0 +1,19 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests.WithoutIoc
+{
+ using System.Collections.Generic;
+ using BBT.StrategyPattern.Tests.ExampleStrategyImpl;
+
+ public class MemoryOperatorStrategyLocator : IStrategyLocator
+ {
+ public IEnumerable GetAllStrategies()
+ {
+ return new List()
+ {
+ new AdditionStrategy(),
+ new SubstractionStrategy(),
+ };
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.Tests/WithoutIocTest.cs b/src/BBT.StrategyPattern.Tests/WithoutIocTest.cs
new file mode 100644
index 0000000..cdf3ef9
--- /dev/null
+++ b/src/BBT.StrategyPattern.Tests/WithoutIocTest.cs
@@ -0,0 +1,32 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern.Tests
+{
+ using BBT.StrategyPattern.Tests.Data;
+ using BBT.StrategyPattern.Tests.ExampleStrategyImpl;
+ using BBT.StrategyPattern.Tests.WithoutIoc;
+ using FluentAssertions;
+ using Xunit;
+
+ public class WithoutIocTest
+ {
+ [Fact]
+ public void GenericStrategyWorksInMemory()
+ {
+ var calc1 = new CalculationInput() { Number1 = 5, Number2 = 3 };
+ var op1 = new Operator() { Operation = OperatorEnum.Addition };
+ var op2 = new Operator() { Operation = OperatorEnum.Subtraktion };
+
+ var factory = new MemoryOperatorStrategyLocator();
+ var strategyProvider = new GenericStrategyProvider(factory);
+
+ IOperatorStrategy strategy;
+
+ strategy = strategyProvider.GetStrategy(op1);
+ strategy.DoCalculate(calc1).Should().Be(8);
+
+ strategy = strategyProvider.GetStrategy(op2);
+ strategy.DoCalculate(calc1).Should().Be(2);
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern.ruleset b/src/BBT.StrategyPattern.ruleset
new file mode 100644
index 0000000..a4324ea
--- /dev/null
+++ b/src/BBT.StrategyPattern.ruleset
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern.sln b/src/BBT.StrategyPattern.sln
new file mode 100644
index 0000000..6f9c470
--- /dev/null
+++ b/src/BBT.StrategyPattern.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28307.271
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BBT.StrategyPattern", "BBT.StrategyPattern\BBT.StrategyPattern.csproj", "{2F38B821-95F8-4560-B08E-9796C44D0C86}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BBT.StrategyPattern.Tests", "BBT.StrategyPattern.Tests\BBT.StrategyPattern.Tests.csproj", "{86D8402D-88CF-4887-A9BC-5662FC23BAFE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2F38B821-95F8-4560-B08E-9796C44D0C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2F38B821-95F8-4560-B08E-9796C44D0C86}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2F38B821-95F8-4560-B08E-9796C44D0C86}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2F38B821-95F8-4560-B08E-9796C44D0C86}.Release|Any CPU.Build.0 = Release|Any CPU
+ {86D8402D-88CF-4887-A9BC-5662FC23BAFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86D8402D-88CF-4887-A9BC-5662FC23BAFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86D8402D-88CF-4887-A9BC-5662FC23BAFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86D8402D-88CF-4887-A9BC-5662FC23BAFE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {9E9EFC94-8A6D-473C-BA4C-2C793E565BA6}
+ EndGlobalSection
+EndGlobal
diff --git a/src/BBT.StrategyPattern.sln.DotSettings b/src/BBT.StrategyPattern.sln.DotSettings
new file mode 100644
index 0000000..7cc51a4
--- /dev/null
+++ b/src/BBT.StrategyPattern.sln.DotSettings
@@ -0,0 +1,3 @@
+
+ DO_NOT_SHOW
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern/AssemblyInfo.cs b/src/BBT.StrategyPattern/AssemblyInfo.cs
new file mode 100644
index 0000000..b5249c5
--- /dev/null
+++ b/src/BBT.StrategyPattern/AssemblyInfo.cs
@@ -0,0 +1 @@
+[assembly: System.CLSCompliant(true)]
diff --git a/src/BBT.StrategyPattern/BBT.StrategyPattern.csproj b/src/BBT.StrategyPattern/BBT.StrategyPattern.csproj
new file mode 100644
index 0000000..2a607b9
--- /dev/null
+++ b/src/BBT.StrategyPattern/BBT.StrategyPattern.csproj
@@ -0,0 +1,39 @@
+
+
+
+ netstandard2.0
+ BBT.StrategyPattern
+ BBT Software AG
+ BBT.StrategyPattern
+ A strategy pattern implementation for .NET
+ Copyright © BBT Software AG
+ ..\BBT.StrategyPattern.ruleset
+ bin\$(Configuration)\BBT.StrategyPattern.XML
+ bin\$(Configuration)\
+ true
+
+
+
+ full
+
+
+
+ pdbonly
+
+
+
+
+ all
+
+
+ all
+
+
+
+
+
+ <_Parameter1>$(MSBuildProjectName).Tests
+
+
+
+
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern/GenericInstanceCreator.cs b/src/BBT.StrategyPattern/GenericInstanceCreator.cs
new file mode 100644
index 0000000..d0a20d0
--- /dev/null
+++ b/src/BBT.StrategyPattern/GenericInstanceCreator.cs
@@ -0,0 +1,23 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ ///
+ /// Generic implementation of .
+ ///
+ /// Interface type which is returned.
+ /// Class which is instantiated.
+ public class GenericInstanceCreator : IInstanceCreator
+ where TInterface : class
+ where TClass : TInterface, new()
+ {
+ ///
+ /// See .
+ ///
+ /// A new instance of .
+ public TInterface Create()
+ {
+ return new TClass();
+ }
+ }
+}
diff --git a/src/BBT.StrategyPattern/GenericStrategyProvider.cs b/src/BBT.StrategyPattern/GenericStrategyProvider.cs
new file mode 100644
index 0000000..35b6af0
--- /dev/null
+++ b/src/BBT.StrategyPattern/GenericStrategyProvider.cs
@@ -0,0 +1,47 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ using System;
+ using System.Globalization;
+ using System.Linq;
+
+ ///
+ /// See .
+ ///
+ /// See link above.
+ /// See link above.
+ public class GenericStrategyProvider
+ : IGenericStrategyProvider
+ where TStrategy : IGenericStrategy
+ {
+ private readonly IStrategyLocator strategyLocator;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The which can locate the strategies of which the responsible on is provided.
+ public GenericStrategyProvider(IStrategyLocator strategyLocator)
+ {
+ this.strategyLocator = strategyLocator ?? throw new ArgumentNullException(nameof(strategyLocator));
+ }
+
+ ///
+ /// See .
+ ///
+ /// See .
+ /// See .
+ public TStrategy GetStrategy(TCriterion criterion)
+ {
+ var strategies = this.strategyLocator.GetAllStrategies();
+
+ // If no strategies for TStrategy can be found.
+ if (!strategies.Any())
+ {
+ throw new InvalidOperationException($"No strategies of {typeof(TStrategy).Name} are available from the locator.");
+ }
+
+ return strategies.Single(x => x.IsResponsible(criterion));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BBT.StrategyPattern/IGenericStrategy.cs b/src/BBT.StrategyPattern/IGenericStrategy.cs
new file mode 100644
index 0000000..6634119
--- /dev/null
+++ b/src/BBT.StrategyPattern/IGenericStrategy.cs
@@ -0,0 +1,18 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ ///
+ /// The generic strategy for criteria .
+ ///
+ /// The type of criterium.
+ public interface IGenericStrategy
+ {
+ ///
+ /// Gets a value indicating whether this strategy is responsible for .
+ ///
+ /// The criterion ( ) which is used to determine if this strategy is responsible.
+ /// True if the strategy is deemed responsible.
+ bool IsResponsible(T criterion);
+ }
+}
diff --git a/src/BBT.StrategyPattern/IGenericStrategyProvider.cs b/src/BBT.StrategyPattern/IGenericStrategyProvider.cs
new file mode 100644
index 0000000..02270fb
--- /dev/null
+++ b/src/BBT.StrategyPattern/IGenericStrategyProvider.cs
@@ -0,0 +1,21 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ ///
+ /// Generic strategy factory for criteria of type
+ /// and strategies of type .
+ ///
+ /// The type of strategy.
+ /// The type of criterium.
+ public interface IGenericStrategyProvider
+ where TStrategy : IGenericStrategy
+ {
+ ///
+ /// Gets the strategy corresponding to .
+ ///
+ /// Criterion for which the strategy must be responsible.
+ /// A strategy matching . If no or more than one strategies are found an exception is thrown.
+ TStrategy GetStrategy(TCriterion criterion);
+ }
+}
diff --git a/src/BBT.StrategyPattern/IInstanceCreator.cs b/src/BBT.StrategyPattern/IInstanceCreator.cs
new file mode 100644
index 0000000..49206c9
--- /dev/null
+++ b/src/BBT.StrategyPattern/IInstanceCreator.cs
@@ -0,0 +1,20 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ ///
+ /// Helper interface to instantiate instances.
+ ///
+ /// The interface type.
+ /// The class type, must inherit from .
+ public interface IInstanceCreator
+ where TInterface : class
+ where TClass : TInterface, new()
+ {
+ ///
+ /// Creates an instance of type .
+ ///
+ /// Returns a new instance of .
+ TInterface Create();
+ }
+}
diff --git a/src/BBT.StrategyPattern/IStrategyLocator.cs b/src/BBT.StrategyPattern/IStrategyLocator.cs
new file mode 100644
index 0000000..15cb831
--- /dev/null
+++ b/src/BBT.StrategyPattern/IStrategyLocator.cs
@@ -0,0 +1,19 @@
+// Copyright © BBT Software AG. All rights reserved.
+
+namespace BBT.StrategyPattern
+{
+ using System.Collections.Generic;
+
+ ///
+ /// Defines how strategies are located.
+ ///
+ /// Strategy type to locate.
+ public interface IStrategyLocator
+ {
+ ///
+ /// Returns all strategies of .
+ ///
+ /// See above.
+ IEnumerable GetAllStrategies();
+ }
+}
diff --git a/tools/packages.config b/tools/packages.config
new file mode 100644
index 0000000..e7f7fdd
--- /dev/null
+++ b/tools/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file