diff --git a/2014-12-08/SolidExample/SolidExample.sln b/2014-12-08/SolidExample/SolidExample.sln
new file mode 100644
index 0000000..10f2352
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolidExample", "SolidExample\SolidExample.csproj", "{911E78F5-7543-4EB4-83D5-C037321C373A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {911E78F5-7543-4EB4-83D5-C037321C373A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {911E78F5-7543-4EB4-83D5-C037321C373A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {911E78F5-7543-4EB4-83D5-C037321C373A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {911E78F5-7543-4EB4-83D5-C037321C373A}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/2014-12-08/SolidExample/SolidExample/App.config b/2014-12-08/SolidExample/SolidExample/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2014-12-08/SolidExample/SolidExample/Cars.csv b/2014-12-08/SolidExample/SolidExample/Cars.csv
new file mode 100644
index 0000000..37b82a0
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/Cars.csv
@@ -0,0 +1,6 @@
+Year,Make,Model,Description,Price
+1997,Ford,E350,"ac, abs, moon",3000.00
+1999,Chevy,"Venture ""Extended Edition""","",4900.00
+1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00
+1996,Jeep,Grand Cherokee,"MUST SELL!
+air, moon roof, loaded",4799.00
\ No newline at end of file
diff --git a/2014-12-08/SolidExample/SolidExample/DataReaderStringIndexedWrapper.cs b/2014-12-08/SolidExample/SolidExample/DataReaderStringIndexedWrapper.cs
new file mode 100644
index 0000000..eb2900b
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/DataReaderStringIndexedWrapper.cs
@@ -0,0 +1,31 @@
+using System.Data;
+
+namespace SolidExample
+{
+ ///
+ /// Wraps a DataRow record to provide a consistent indexer interface
+ ///
+ internal class DataRowStringIndexedWrapper : IStringIndexed
+ {
+ private readonly DataRow _row;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ ///
+ public DataRowStringIndexedWrapper(DataRow row)
+ {
+ _row = row;
+ }
+
+ #region IStringIndexed Members
+
+ ///
+ object IStringIndexed.this[string key]
+ {
+ get { return _row[key]; }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/2014-12-08/SolidExample/SolidExample/DataRecordStringIndexedWrapper.cs b/2014-12-08/SolidExample/SolidExample/DataRecordStringIndexedWrapper.cs
new file mode 100644
index 0000000..be7e6ae
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/DataRecordStringIndexedWrapper.cs
@@ -0,0 +1,31 @@
+using System.Data;
+
+namespace SolidExample
+{
+ ///
+ /// Wraps an IDataRecord record to provide a consistent indexer interface
+ ///
+ internal class DataRecordStringIndexedWrapper : IStringIndexed
+ {
+ private readonly IDataRecord _record;
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// A record
+ public DataRecordStringIndexedWrapper(IDataRecord record)
+ {
+ _record = record;
+ }
+
+ #region IStringIndexed Members
+
+ ///
+ object IStringIndexed.this[string key]
+ {
+ get { return _record[key]; }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/2014-12-08/SolidExample/SolidExample/IStringIndexed.cs b/2014-12-08/SolidExample/SolidExample/IStringIndexed.cs
new file mode 100644
index 0000000..e15338b
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/IStringIndexed.cs
@@ -0,0 +1,15 @@
+namespace SolidExample
+{
+ ///
+ /// A contract for instances that offer objects via keyed index
+ ///
+ public interface IStringIndexed
+ {
+ ///
+ /// An indexer by key
+ ///
+ /// A unique string-based key for accessing objects
+ /// A found object at given
+ object this[string key] { get; }
+ }
+}
\ No newline at end of file
diff --git a/2014-12-08/SolidExample/SolidExample/Program.cs b/2014-12-08/SolidExample/SolidExample/Program.cs
new file mode 100644
index 0000000..cb1164c
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/Program.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Odbc;
+using System.Data.OleDb;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SolidExample
+{
+ class Program
+ {
+ private static string cnxTemplate =
+ @"Driver={{Microsoft Text Driver (*.txt; *.csv)}};Dbq={0};Extensions=csv,txt";
+
+ static void Main(string[] args)
+ {
+ /** The Problem **/
+ Console.WriteLine("A standard DataReader:");
+ string connectionString = String.Format(cnxTemplate, Environment.CurrentDirectory);
+ using (var connection = new OdbcConnection(connectionString))
+ {
+ connection.Open();
+ using (var cmd = connection.CreateCommand())
+ {
+ // csv from http://www.wikiwand.com/en/Comma-separated_values#/Example
+ cmd.CommandText = "select * from Cars.csv";
+
+ using (var reader = cmd.ExecuteReader())
+ while (reader.Read())
+ {
+ OverloadedDumpRow(reader);
+ }
+ }
+ }
+ Console.WriteLine();
+
+ Console.WriteLine("A standard DataSet example.");
+ using (var connection = new OdbcConnection(connectionString))
+ {
+ connection.Open();
+
+ var adapter = new OdbcDataAdapter("SELECT * FROM Cars.csv", connection);
+
+ DataSet ds = new DataSet("Temp");
+ adapter.Fill(ds);
+
+ foreach (DataRow row in ds.Tables[0].Rows)
+ {
+ OverloadedDumpRow(row);
+ }
+ }
+ Console.WriteLine();
+
+ /** The Solution **/
+ Console.WriteLine("A wrapped DataReader (shared mapping function):");
+ using (var connection = new OdbcConnection(connectionString))
+ {
+ connection.Open();
+ using (var cmd = connection.CreateCommand())
+ {
+ // csv from http://www.wikiwand.com/en/Comma-separated_values#/Example
+ cmd.CommandText = "select * from Cars.csv";
+
+ using (var reader = cmd.ExecuteReader())
+ while (reader.Read())
+ {
+ DumpRow(new DataRecordStringIndexedWrapper(reader));
+ }
+ }
+ }
+ Console.WriteLine();
+
+ Console.WriteLine("A wrapped DataSet example (shared mapping function).");
+ using (var connection = new OdbcConnection(connectionString))
+ {
+ connection.Open();
+
+ var adapter = new OdbcDataAdapter("SELECT * FROM Cars.csv", connection);
+
+ DataSet ds = new DataSet("Temp");
+ adapter.Fill(ds);
+
+ foreach (DataRow row in ds.Tables[0].Rows)
+ {
+ DumpRow(new DataRowStringIndexedWrapper(row));
+ }
+ }
+
+ Console.ReadLine();
+ }
+
+ ///
+ /// Example function operatoring on a single instance implementing IDataRecord
+ ///
+ ///
+ static void OverloadedDumpRow(IDataRecord row)
+ {
+ Console.WriteLine("A {0} {1} {2}",
+ row["Year"], row["Make"], row["Model"]);
+ }
+
+ ///
+ /// A needlessly redundant method to achieve the same as IDataRecord version above
+ ///
+ ///
+ static void OverloadedDumpRow(DataRow row)
+ {
+ Console.WriteLine("A {0} {1} {2}",
+ row["Year"], row["Make"], row["Model"]);
+ }
+
+ ///
+ /// An adapter is created to implement a known interface.
+ ///
+ ///
+ static void DumpRow(IStringIndexed record)
+ {
+ Console.WriteLine("A {0} {1} {2}",
+ record["Year"], record["Make"], record["Model"]);
+ }
+ }
+}
diff --git a/2014-12-08/SolidExample/SolidExample/Properties/AssemblyInfo.cs b/2014-12-08/SolidExample/SolidExample/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..89c88d6
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SolidExample")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SolidExample")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("840bf2c0-b6e5-4dd8-8fd3-d8060d1228c8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/2014-12-08/SolidExample/SolidExample/SolidExample.csproj b/2014-12-08/SolidExample/SolidExample/SolidExample.csproj
new file mode 100644
index 0000000..d32c2ea
--- /dev/null
+++ b/2014-12-08/SolidExample/SolidExample/SolidExample.csproj
@@ -0,0 +1,64 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {911E78F5-7543-4EB4-83D5-C037321C373A}
+ Exe
+ Properties
+ SolidExample
+ SolidExample
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
\ No newline at end of file