diff --git a/Chapter11/AbstractionDesign/AbstractionDesign.sln b/Chapter11/AbstractionDesign/AbstractionDesign.sln
new file mode 100644
index 0000000..43db99e
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31112.23
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbstractionDesign", "AbstractionDesign\AbstractionDesign.csproj", "{5B600C0B-F23D-491E-9931-9A53C125EB71}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5B600C0B-F23D-491E-9931-9A53C125EB71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B600C0B-F23D-491E-9931-9A53C125EB71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B600C0B-F23D-491E-9931-9A53C125EB71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B600C0B-F23D-491E-9931-9A53C125EB71}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {F37435DC-CFB8-4516-86C0-687625610CB9}
+ EndGlobalSection
+EndGlobal
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/AbstractionDesign.csproj b/Chapter11/AbstractionDesign/AbstractionDesign/AbstractionDesign.csproj
new file mode 100644
index 0000000..c48ffd9
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/AbstractionDesign.csproj
@@ -0,0 +1,59 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {5B600C0B-F23D-491E-9931-9A53C125EB71}
+ Exe
+ AbstractionDesign
+ AbstractionDesign
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/App.config b/Chapter11/AbstractionDesign/AbstractionDesign/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Program.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Program.cs
new file mode 100644
index 0000000..3f937c8
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Program.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using AbstractionDesign.Tools;
+
+namespace AbstractionDesign
+{
+ class Program
+ {
+ private delegate void CommandHandler(IEnumerable parameters);
+ private static Sensor CurrentSensor;
+
+ static void Main(string[] args)
+ {
+ while (true)
+ {
+ Console.Write("> ");
+ var input = Console.ReadLine() ?? string.Empty;
+ var tokens = input.Split(' ');
+
+ if (tokens.Length < 1)
+ {
+ Console.WriteLine("Please supply a command");
+ continue;
+ }
+
+ var command = tokens.First();
+ var parameters = tokens.Skip(1);
+
+ var handlers = new Dictionary
+ {
+ {"select", SelectTool},
+ {"move", Move},
+ {"zoom", Zoom},
+ {"capture-image", CaptureImage},
+ {"measure-height", MeasureHeight},
+ {"pitch", Pitch},
+ {"roll", Roll},
+ {"raise", Raise},
+ {"lower", Lower},
+ {"get-pressure", GetPressure},
+ {"quit", Quit}
+ };
+
+ if (!handlers.ContainsKey(command))
+ {
+ Console.WriteLine($"Unrecognized command: {command}");
+ }
+ else
+ {
+ handlers[command].Invoke(parameters);
+ }
+ }
+ }
+
+ private static void SelectTool(IEnumerable parameters)
+ {
+ switch (parameters.FirstOrDefault())
+ {
+ case "camera":
+ CurrentSensor = new Camera();
+ Console.WriteLine("Tool is now the camera");
+ break;
+ case "laser":
+ CurrentSensor = new Laser();
+ Console.WriteLine("Tool is now the laser");
+ break;
+ case "touchprobe":
+ CurrentSensor = new TouchProbe();
+ Console.WriteLine("Tool is now the touch probe");
+ break;
+ default:
+ Console.WriteLine("Possible Tools are camera, laser or touchprobe");
+ break;
+ }
+ }
+
+ private static void Move(IEnumerable parameters)
+ {
+ if (CurrentSensor != null)
+ {
+ float x, y;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out x) && float.TryParse(parameters.Skip(1).FirstOrDefault(), out y))
+ {
+ CurrentSensor.Move(x, y);
+ }
+ else
+ {
+ Console.WriteLine("Move requires two floating-point parameters (eg: 1.5 2.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select a tool!");
+ }
+ }
+
+ private static void Zoom(IEnumerable parameters)
+ {
+ var camera = CurrentSensor as Camera;
+
+ if (camera != null)
+ {
+ float level;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out level))
+ {
+ camera.Zoom(level);
+ }
+ else
+ {
+ Console.WriteLine("Zooming camera requires a floating-point parameter (eg: 1.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select camera to zoom!");
+ }
+ }
+
+ private static void CaptureImage(IEnumerable parameters)
+ {
+ var camera = CurrentSensor as Camera;
+
+ if (camera != null)
+ {
+ Console.WriteLine(camera.Capture()); //TODO
+ }
+ else
+ {
+ Console.WriteLine("Must select camera to capture an image!");
+ }
+ }
+
+ private static void MeasureHeight(IEnumerable parameters)
+ {
+ var laser = CurrentSensor as Laser;
+
+ if (laser != null)
+ {
+ Console.WriteLine(laser.Measure());
+ }
+ else
+ {
+ Console.WriteLine("Must select laser to measure height!");
+ }
+ }
+
+ private static void Pitch(IEnumerable parameters)
+ {
+ var touchProbe = CurrentSensor as TouchProbe;
+
+ if (touchProbe != null)
+ {
+ float level;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out level))
+ {
+ touchProbe.Pitch(level);
+ }
+ else
+ {
+ Console.WriteLine("Pitch requires a floating-point parameter (eg: 1.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select touch probe to pitch!");
+ }
+ }
+
+ private static void Roll(IEnumerable parameters)
+ {
+ var touchProbe = CurrentSensor as TouchProbe;
+
+ if (touchProbe != null)
+ {
+ float level;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out level))
+ {
+ touchProbe.Roll(level);
+ }
+ else
+ {
+ Console.WriteLine("Roll requires a floating-point parameter (eg: 1.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select touch probe to roll!");
+ }
+ }
+
+ private static void Raise(IEnumerable parameters)
+ {
+ var touchProbe = CurrentSensor as TouchProbe;
+
+ if (touchProbe != null)
+ {
+ float level;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out level))
+ {
+ touchProbe.Raise(level);
+ }
+ else
+ {
+ Console.WriteLine("Raise requires a floating-point parameter (eg: 1.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select touch probe to raise!");
+ }
+ }
+
+ private static void Lower(IEnumerable parameters)
+ {
+ var touchProbe = CurrentSensor as TouchProbe;
+
+ if (touchProbe != null)
+ {
+ float level;
+
+ if (float.TryParse(parameters.FirstOrDefault(), out level))
+ {
+ touchProbe.Lower(level);
+ }
+ else
+ {
+ Console.WriteLine("Lower requires a floating-point parameter (eg: 1.5)");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Must select touch probe to lower!");
+ }
+ }
+
+ private static void GetPressure(IEnumerable parameters)
+ {
+ var touchProbe = CurrentSensor as TouchProbe;
+
+ if (touchProbe != null)
+ {
+ Console.WriteLine($"Pressure: {touchProbe.GetPressure().Value}");
+ }
+ else
+ {
+ Console.WriteLine("Must select touch probe to get pressure!");
+ }
+ }
+
+ private static void Quit(IEnumerable parameters)
+ {
+ Environment.Exit(0);
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Properties/AssemblyInfo.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2d048ef
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die einer Assembly zugeordnet sind.
+[assembly: AssemblyTitle("AbstractionDesign")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AbstractionDesign")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
+// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
+// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("5b600c0b-f23d-491e-9931-9a53c125eb71")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
+// indem Sie "*" wie unten gezeigt eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Camera.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Camera.cs
new file mode 100644
index 0000000..725f744
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Camera.cs
@@ -0,0 +1,18 @@
+using System.Drawing;
+
+namespace AbstractionDesign.Tools
+{
+ public class Camera : Sensor
+ {
+ private float _zoomLevel;
+
+ public Camera() : base("camera") { }
+
+ public void Zoom(float level) => _zoomLevel = level;
+
+ public Image Capture()
+ {
+ return new Bitmap(100, 100);
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Laser.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Laser.cs
new file mode 100644
index 0000000..913d24e
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Laser.cs
@@ -0,0 +1,12 @@
+namespace AbstractionDesign.Tools
+{
+ public class Laser : Sensor
+ {
+ public Laser() : base("laser") { }
+
+ public float Measure()
+ {
+ return 0f;
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Sensor.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Sensor.cs
new file mode 100644
index 0000000..0ce7d63
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/Sensor.cs
@@ -0,0 +1,19 @@
+namespace AbstractionDesign.Tools
+{
+ public abstract class Sensor
+ {
+ protected readonly string Name;
+ protected float X, Y;
+
+ protected Sensor(string name)
+ {
+ Name = name;
+ }
+
+ public virtual void Move(float x, float y)
+ {
+ X += x;
+ Y += y;
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesign/AbstractionDesign/Tools/TouchProbe.cs b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/TouchProbe.cs
new file mode 100644
index 0000000..c37f020
--- /dev/null
+++ b/Chapter11/AbstractionDesign/AbstractionDesign/Tools/TouchProbe.cs
@@ -0,0 +1,45 @@
+namespace AbstractionDesign.Tools
+{
+ public class TouchProbe : Sensor
+ {
+ private float _pitch, _roll;
+ private float _height;
+
+ public TouchProbe() : base("touchprobe") { }
+
+ public void Pitch(float pitch)
+ {
+ _pitch += pitch;
+ }
+
+ public void Roll(float roll)
+ {
+ _roll += roll;
+ }
+
+ public void Raise(float height)
+ {
+ _height += height;
+ }
+
+ public void Lower(float height)
+ {
+ _height -= height;
+ }
+
+ public PoundsPerSquareInch GetPressure()
+ {
+ return new PoundsPerSquareInch(13.2f);
+ }
+ }
+
+ public struct PoundsPerSquareInch
+ {
+ public PoundsPerSquareInch(float value)
+ {
+ Value = value;
+ }
+
+ public float Value { get; private set; }
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities.sln b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities.sln
new file mode 100644
index 0000000..d221761
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31112.23
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbstractionDesignCapabilities", "AbstractionDesignCapabilities\AbstractionDesignCapabilities.csproj", "{B78E76C1-7798-479A-AB80-DF6248FE6FD7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B78E76C1-7798-479A-AB80-DF6248FE6FD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B78E76C1-7798-479A-AB80-DF6248FE6FD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B78E76C1-7798-479A-AB80-DF6248FE6FD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B78E76C1-7798-479A-AB80-DF6248FE6FD7}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B4B26245-66B6-4B06-A5CF-1A0ABFA34A1C}
+ EndGlobalSection
+EndGlobal
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/AbstractionDesignCapabilities.csproj b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/AbstractionDesignCapabilities.csproj
new file mode 100644
index 0000000..5c98091
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/AbstractionDesignCapabilities.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B78E76C1-7798-479A-AB80-DF6248FE6FD7}
+ Exe
+ AbstractionDesignCapabilities
+ AbstractionDesignCapabilities
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/App.config b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IHeightAdjustable.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IHeightAdjustable.cs
new file mode 100644
index 0000000..4fbe2d1
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IHeightAdjustable.cs
@@ -0,0 +1,8 @@
+namespace AbstractionDesignCapabilities.Interfaces
+{
+ public interface IHeightAdjustable
+ {
+ void Raise(float height);
+ void Lower(float height);
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMeasurable.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMeasurable.cs
new file mode 100644
index 0000000..07ce2c5
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMeasurable.cs
@@ -0,0 +1,9 @@
+using System.IO;
+
+namespace AbstractionDesignCapabilities.Interfaces
+{
+ public interface IMeasurable
+ {
+ void WriteMeasurement(TextWriter writer);
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMovable.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMovable.cs
new file mode 100644
index 0000000..3c1e274
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IMovable.cs
@@ -0,0 +1,7 @@
+namespace AbstractionDesignCapabilities.Interfaces
+{
+ public interface IMovable
+ {
+ void Move(float x, float y);
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IRotatable.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IRotatable.cs
new file mode 100644
index 0000000..525edb0
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/IRotatable.cs
@@ -0,0 +1,8 @@
+namespace AbstractionDesignCapabilities.Interfaces
+{
+ public interface IRotatable
+ {
+ void Pitch(float pitch);
+ void Roll(float roll);
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/ISensor.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/ISensor.cs
new file mode 100644
index 0000000..429c65f
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Interfaces/ISensor.cs
@@ -0,0 +1,7 @@
+namespace AbstractionDesignCapabilities.Interfaces
+{
+ public interface ISensor
+ {
+ string GetName();
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Program.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Program.cs
new file mode 100644
index 0000000..bdc4f43
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Program.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using AbstractionDesignCapabilities.Interfaces;
+using AbstractionDesignCapabilities.Tools;
+
+namespace AbstractionDesignCapabilities
+{
+ class Program
+ {
+ private delegate void CommandHandler(IEnumerable parameters);
+ private static ISensor CurrentSensor;
+
+ static void Main(string[] args)
+ {
+ while (true)
+ {
+ Console.Write("> ");
+ var input = Console.ReadLine() ?? string.Empty;
+ var tokens = input.Split(' ');
+
+ if (tokens.Length < 1)
+ {
+ Console.WriteLine("Please supply a command");
+ continue;
+ }
+
+ var command = tokens.First();
+ var parameters = tokens.Skip(1);
+
+ var handlers = new Dictionary
+ {
+ {"select", SelectTool},
+ {"move", Move},
+ {"measure", Measure},
+ {"rotate", Rotate},
+ {"adjust-height", AdjustHeight},
+ {"quit", Quit}
+ };
+
+ if (!handlers.ContainsKey(command))
+ {
+ Console.WriteLine($"Unrecognized command: {command}");
+ }
+ else
+ {
+ handlers[command].Invoke(parameters);
+ }
+ }
+ }
+
+ private static void SelectTool(IEnumerable parameters)
+ {
+ switch (parameters.FirstOrDefault())
+ {
+ case "camera":
+ CurrentSensor = new Camera();
+ Console.WriteLine("Tool is now the camera");
+ break;
+ case "laser":
+ CurrentSensor = new Laser();
+ Console.WriteLine("Tool is now the laser");
+ break;
+ case "touchprobe":
+ CurrentSensor = new TouchProbe();
+ Console.WriteLine("Tool is now the touch probe");
+ break;
+ default:
+ Console.WriteLine("Possible Tools are camera, laser or touchprobe");
+ break;
+ }
+ }
+
+ private static void Move(IEnumerable parameters)
+ {
+ var movableSensor = CurrentSensor as IMovable;
+
+ if (movableSensor == null)
+ {
+ Console.WriteLine($"Current sensor '{CurrentSensor?.GetName()}' is not movable");
+ return;
+ }
+
+ float x, y;
+ if (float.TryParse(parameters.FirstOrDefault(), out x) && float.TryParse(parameters.Skip(1).FirstOrDefault(), out y))
+ {
+ movableSensor.Move(x, y);
+ }
+ else
+ {
+ Console.WriteLine("Move requires two floating-point parameters (eg: 1.5)");
+ }
+ }
+
+ private static void Measure(IEnumerable parameters)
+ {
+ var measureableSensor = CurrentSensor as IMeasurable;
+
+ if (measureableSensor == null)
+ {
+ Console.WriteLine($"Current sensor '{CurrentSensor?.GetName()}' is not measurable");
+ return;
+ }
+
+ measureableSensor.WriteMeasurement(Console.Out);
+ }
+
+ private static void Rotate(IEnumerable parameters)
+ {
+ var rotatableSensor = CurrentSensor as IRotatable;
+
+ if (rotatableSensor == null)
+ {
+ Console.WriteLine($"Current sensor '{CurrentSensor?.GetName()}' is not rotatable");
+ return;
+ }
+
+ float value;
+
+ if (parameters.Count() >= 2 && float.TryParse(parameters.Skip(1).FirstOrDefault(), out value))
+ {
+ var direction = parameters.FirstOrDefault();
+ switch (direction)
+ {
+ case "pitch":
+ {
+ rotatableSensor.Pitch(value);
+ break;
+ }
+ case "roll":
+ {
+ rotatableSensor.Roll(value);
+ break;
+ }
+ default:
+ {
+ Console.WriteLine("First parameter to height adjustment must be 'pitch' or 'roll'");
+ break;
+ }
+ }
+ }
+ else
+ {
+ Console.WriteLine("Rotate requires two parameters: 'pitch/roll' and height (eg: 1.5f)");
+ }
+ }
+
+ private static void AdjustHeight(IEnumerable parameters)
+ {
+ var heightAdjustableSensor = CurrentSensor as IHeightAdjustable;
+
+ if (heightAdjustableSensor == null)
+ {
+ Console.WriteLine($"Current sensor '{CurrentSensor?.GetName()}' is not height adjustable");
+ return;
+ }
+
+ float height;
+
+ if (parameters.Count() >= 2 && float.TryParse(parameters.Skip(1).FirstOrDefault(), out height))
+ {
+ var direction = parameters.FirstOrDefault();
+ switch (direction)
+ {
+ case "raise":
+ {
+ heightAdjustableSensor.Raise(height);
+ break;
+ }
+ case "lower":
+ {
+ heightAdjustableSensor.Lower(height);
+ break;
+ }
+ default:
+ {
+ Console.WriteLine("First parameter to height adjustment must be 'raise' or 'lower'");
+ break;
+ }
+ }
+ }
+ else
+ {
+ Console.WriteLine("Height adjustment requires two parameters: 'raise/lower' and height (eg: 1.5f)");
+ }
+ }
+
+ private static void Quit(IEnumerable parameters)
+ {
+ Environment.Exit(0);
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Properties/AssemblyInfo.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..50a6c60
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die einer Assembly zugeordnet sind.
+[assembly: AssemblyTitle("AbstractionDesignCapabilities")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AbstractionDesignCapabilities")]
+[assembly: AssemblyCopyright("Copyright © 2021")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
+// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
+// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("b78e76c1-7798-479a-ab80-df6248fe6fd7")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
+// indem Sie "*" wie unten gezeigt eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Camera.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Camera.cs
new file mode 100644
index 0000000..81d2b86
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Camera.cs
@@ -0,0 +1,42 @@
+using System.Drawing;
+using System.IO;
+using AbstractionDesignCapabilities.Interfaces;
+
+namespace AbstractionDesignCapabilities.Tools
+{
+ public class Camera : ISensor, IMovable, IHeightAdjustable, IMeasurable
+ {
+ private float _zoomLevel;
+ private float _x, _y;
+
+ public Image Capture()
+ {
+ return new Bitmap(100, 100);
+ }
+ public void WriteMeasurement(TextWriter writer)
+ {
+ writer.WriteLine(Capture());
+ }
+
+ public string GetName()
+ {
+ return "camera";
+ }
+
+ public void Raise(float height)
+ {
+ _zoomLevel += height;
+ }
+
+ public void Lower(float height)
+ {
+ _zoomLevel -= height;
+ }
+
+ public void Move(float x, float y)
+ {
+ _x = x;
+ _y = y;
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Laser.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Laser.cs
new file mode 100644
index 0000000..38ea72e
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/Laser.cs
@@ -0,0 +1,30 @@
+using System.IO;
+using AbstractionDesignCapabilities.Interfaces;
+
+namespace AbstractionDesignCapabilities.Tools
+{
+ public class Laser : ISensor, IMovable, IMeasurable
+ {
+ private float _x, _y;
+
+ public float Measure()
+ {
+ return 0f;
+ }
+ public void WriteMeasurement(TextWriter writer)
+ {
+ writer.WriteLine(Measure());
+ }
+
+ public string GetName()
+ {
+ return "laser";
+ }
+
+ public void Move(float x, float y)
+ {
+ _x = x;
+ _y = y;
+ }
+ }
+}
diff --git a/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/TouchProbe.cs b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/TouchProbe.cs
new file mode 100644
index 0000000..d9f35ec
--- /dev/null
+++ b/Chapter11/AbstractionDesignCapabilities/AbstractionDesignCapabilities/Tools/TouchProbe.cs
@@ -0,0 +1,63 @@
+using System.IO;
+using AbstractionDesignCapabilities.Interfaces;
+
+namespace AbstractionDesignCapabilities.Tools
+{
+ public class TouchProbe : ISensor, IMovable, IRotatable, IHeightAdjustable, IMeasurable
+ {
+ private float _x, _y;
+ private float _pitch;
+ private float _roll;
+ private float _height;
+
+ public PoundsPerSquareInch GetPressure()
+ {
+ return new PoundsPerSquareInch(13.2f);
+ }
+ public void WriteMeasurement(TextWriter writer)
+ {
+ writer.WriteLine(GetPressure().Value);
+ }
+
+ public string GetName()
+ {
+ return "touchprobe";
+ }
+
+ public void Move(float x, float y)
+ {
+ _x = x;
+ _y = y;
+ }
+
+ public void Pitch(float pitch)
+ {
+ _pitch = pitch;
+ }
+
+ public void Roll(float roll)
+ {
+ _roll = roll;
+ }
+
+ public void Raise(float height)
+ {
+ _height += height;
+ }
+
+ public void Lower(float height)
+ {
+ _height -= height;
+ }
+ }
+
+ public struct PoundsPerSquareInch
+ {
+ public PoundsPerSquareInch(float value)
+ {
+ Value = value;
+ }
+
+ public float Value { get; private set; }
+ }
+}
diff --git a/Chapter11/EntourageAntiPattern/Domain/Domain.csproj b/Chapter11/EntourageAntiPattern/Domain/Domain.csproj
index 6470a9f..c28aa99 100644
--- a/Chapter11/EntourageAntiPattern/Domain/Domain.csproj
+++ b/Chapter11/EntourageAntiPattern/Domain/Domain.csproj
@@ -32,10 +32,10 @@
- ..\..\..\..\source\repos\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll
+ ..\packages\Iesi.Collections.4.0.0.4000\lib\net40\Iesi.Collections.dll
- ..\..\..\..\source\repos\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll
+ ..\packages\NHibernate.4.0.4.4000\lib\net40\NHibernate.dll