Thrift: C# Bindings.

Summary:
C# generator, library, and MS Build task contributed by imeem.

Reviewed By: mcslee

Test Plan:
Built the Thrift compiler and generated some C# code.
I'd love to say I installed Mono or Portable.NET and built the C# code,
but I did not.

Revert Plan: ok


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665421 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4375a52
--- /dev/null
+++ b/lib/csharp/ThriftMSBuildTask/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("ThriftMSBuildTask")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ThriftMSBuildTask")]
+[assembly: AssemblyCopyright("Copyright ©  2007")]
+[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("5095e09d-7b95-4be1-b250-e1c1db1c485e")]
+
+// 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/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs b/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs
new file mode 100644
index 0000000..9cf5f41
--- /dev/null
+++ b/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
+using Microsoft.Build.Tasks;
+using System.IO;
+using System.Diagnostics;
+
+namespace ThriftMSBuildTask
+{
+	/// <summary>
+	/// MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll
+	/// </summary>
+	public class ThriftBuild : Task
+	{
+		/// <summary>
+		/// The full path to the thrift.exe compiler
+		/// </summary>
+		[Required]
+		public ITaskItem ThriftExecutable
+		{
+			get;
+			set;
+		}
+
+		/// <summary>
+		/// The full path to a thrift.dll C# library
+		/// </summary>
+		[Required]
+		public ITaskItem ThriftLibrary
+		{
+			get;
+			set;
+		}
+
+		/// <summary>
+		/// A direcotry containing .thrift files
+		/// </summary>
+		[Required]
+		public ITaskItem ThriftDefinitionDir
+		{
+			get;
+			set;
+		}
+
+		/// <summary>
+		/// The name of the auto-gen and compiled thrift library. It will placed in
+		/// the same directory as ThriftLibrary
+		/// </summary>
+		[Required]
+		public ITaskItem OutputName
+		{
+			get;
+			set;
+		}
+
+		/// <summary>
+		/// The full path to the compiled ThriftLibrary. This allows msbuild tasks to use this
+		/// output as a variable for use elsewhere.
+		/// </summary>
+		[Output]
+		public ITaskItem ThriftImplementation
+		{
+			get { return thriftImpl; }
+		}
+
+		private ITaskItem thriftImpl;
+		private const string lastCompilationName = "LAST_COMP_TIMESTAMP";
+
+		//use the Message Build Task to write something to build log
+		private void LogMessage(string text, MessageImportance importance)
+		{
+			Message m = new Message();
+			m.Text = text;
+			m.Importance = importance.ToString();
+			m.BuildEngine = this.BuildEngine;
+			m.Execute();
+		}
+
+		//recursively find .cs files in srcDir, paths should initially be non-null and empty
+		private void FindSourcesHelper(string srcDir, List<string> paths)
+		{
+			string[] files = Directory.GetFiles(srcDir, "*.cs");
+			foreach (string f in files)
+			{
+				paths.Add(f);
+			}
+			string[] dirs = Directory.GetDirectories(srcDir);
+			foreach (string dir in dirs)
+			{
+				FindSourcesHelper(dir, paths);
+			}
+		}
+
+		/// <summary>
+		/// Quote paths with spaces
+		/// </summary>
+		private string SafePath(string path)
+		{
+			if (path.Contains(' ') && !path.StartsWith("\""))
+			{
+				return "\"" + path + "\"";
+			}
+			return path;
+		}
+
+		private ITaskItem[] FindSources(string srcDir)
+		{
+			List<string> files = new List<string>();
+			FindSourcesHelper(srcDir, files);
+			ITaskItem[] items = new ITaskItem[files.Count];
+			for (int i = 0; i < items.Length; i++)
+			{
+				items[i] = new TaskItem(files[i]);
+			}
+			return items;
+		}
+
+		private string LastWriteTime(string defDir)
+		{
+			string[] files = Directory.GetFiles(defDir, "*.thrift");
+			DateTime d = (new DirectoryInfo(defDir)).LastWriteTime;
+			foreach(string file in files)
+			{
+				FileInfo f = new FileInfo(file);
+				DateTime curr = f.LastWriteTime;
+				if (DateTime.Compare(curr, d) > 0)
+				{
+					d = curr;
+				}
+			}
+			return d.ToFileTimeUtc().ToString();
+		}
+
+		public override bool Execute()
+		{
+			string defDir = SafePath(ThriftDefinitionDir.ItemSpec);
+			//look for last compilation timestamp
+			string lastBuildPath = Path.Combine(defDir, lastCompilationName);
+			DirectoryInfo defDirInfo = new DirectoryInfo(defDir);
+			string lastWrite = LastWriteTime(defDir);
+			if (File.Exists(lastBuildPath))
+			{
+				string lastComp = File.ReadAllText(lastBuildPath);
+
+				if (lastComp == lastWrite)
+				{
+					//the .thrift dir hasn't been written to since last compilation, don't need to do anything
+					LogMessage("ThriftImpl up-to-date", MessageImportance.Normal);
+					return true;
+				}
+			}
+
+			//find the directory of the thriftlibrary (that's where output will go)
+			FileInfo thriftLibInfo = new FileInfo(SafePath(ThriftLibrary.ItemSpec));
+			string thriftDir = thriftLibInfo.Directory.FullName;
+
+			string genDir = Path.Combine(thriftDir, "gen-csharp");
+			if (Directory.Exists(genDir))
+			{
+				Directory.Delete(genDir, true);
+			}
+			
+			//run the thrift executable to generate C#
+			foreach (string thriftFile in Directory.GetFiles(defDir, "*.thrift"))
+			{
+				LogMessage("Generating code for: " + thriftFile, MessageImportance.Normal);
+				Process p = new Process();
+				p.StartInfo.FileName = SafePath(ThriftExecutable.ItemSpec);
+				p.StartInfo.Arguments = "-csharp -o " + SafePath(thriftDir) + " -r " + thriftFile;
+				p.StartInfo.UseShellExecute = false;
+				p.StartInfo.CreateNoWindow = true;
+				p.StartInfo.RedirectStandardOutput = false;
+				p.Start();
+				p.WaitForExit();
+			}
+
+			Csc csc = new Csc();
+			csc.TargetType = "library";
+			csc.References = new ITaskItem[] { new TaskItem(ThriftLibrary.ItemSpec) };
+			csc.EmitDebugInformation = true;
+			string outputPath = Path.Combine(thriftDir, OutputName.ItemSpec);
+			csc.OutputAssembly = new TaskItem(outputPath);
+			csc.Sources = FindSources(Path.Combine(thriftDir, "gen-csharp"));
+			csc.BuildEngine = this.BuildEngine;
+			LogMessage("Compiling generated cs...", MessageImportance.Normal);
+			if (!csc.Execute())
+			{
+				return false;
+			}
+
+			//write file to defDir to indicate a build was successfully completed
+			File.WriteAllText(lastBuildPath, lastWrite);
+
+			thriftImpl = new TaskItem(outputPath);
+
+			return true;
+		}
+	}
+}
diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj
new file mode 100644
index 0000000..68c6bd1
--- /dev/null
+++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{EC0A0231-66EA-4593-A792-C6CA3BB8668E}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>ThriftMSBuildTask</RootNamespace>
+    <AssemblyName>ThriftMSBuildTask</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Microsoft.Build.Framework" />
+    <Reference Include="Microsoft.Build.Tasks" />
+    <Reference Include="Microsoft.Build.Utilities" />
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ThriftBuild.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs
new file mode 100644
index 0000000..36f03d0
--- /dev/null
+++ b/lib/csharp/src/Protocol/TBinaryProtocol.cs
@@ -0,0 +1,386 @@
+//
+//  TBinaryProtocol.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//		Will Palmeri <will@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Transport;
+
+namespace Thrift.Protocol
+{
+	public class TBinaryProtocol : TProtocol
+	{
+		protected const uint VERSION_MASK = 0xffff0000;
+		protected const uint VERSION_1 = 0x80010000;
+
+		protected bool strictRead_ = false;
+		protected bool strictWrite_ = true;
+
+		protected int readLength_;
+		protected bool checkReadLength_ = false;
+
+
+		#region BinaryProtocol Factory
+		 /**
+		  * Factory
+		  */
+		  public class Factory : TProtocolFactory {
+
+			  protected bool strictRead_ = false;
+			  protected bool strictWrite_ = true;
+
+			  public Factory()
+				  :this(false, true)
+			  {
+			  }
+
+			  public Factory(bool strictRead, bool strictWrite)
+			  {
+				  strictRead_ = strictRead;
+				  strictWrite_ = strictWrite;
+			  }
+
+			public TProtocol GetProtocol(TTransport trans) {
+			  return new TBinaryProtocol(trans, strictRead_, strictWrite_);
+			}
+		  }
+
+		#endregion
+
+		public TBinaryProtocol(TTransport trans)
+			: this(trans, false, true)
+		{
+		}
+
+		public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
+			:base(trans)
+		{
+			strictRead_ = strictRead;
+			strictWrite_ = strictWrite;
+		}
+
+		#region Write Methods
+
+		public override void WriteMessageBegin(TMessage message)
+		{
+			if (strictWrite_)
+			{
+				uint version = VERSION_1 | (uint)(message.Type);
+				WriteI32((int)version);
+				WriteString(message.Name);
+				WriteI32(message.SeqID);
+			}
+			else
+			{
+				WriteString(message.Name);
+				WriteByte((byte)message.Type);
+				WriteI32(message.SeqID);
+			}
+		}
+
+		public override void WriteMessageEnd()
+		{
+		}
+
+		public override void WriteStructBegin(TStruct struc)
+		{
+		}
+
+		public override void WriteStructEnd()
+		{
+		}
+
+		public override void WriteFieldBegin(TField field)
+		{
+			WriteByte((byte)field.Type);
+			WriteI16(field.ID);
+		}
+
+		public override void WriteFieldEnd()
+		{
+		}
+
+		public override void WriteFieldStop()
+		{
+			WriteByte((byte)TType.Stop);
+		}
+
+		public override void WriteMapBegin(TMap map)
+		{
+			WriteByte((byte)map.KeyType);
+			WriteByte((byte)map.ValueType);
+			WriteI32(map.Count);
+		}
+
+		public override void WriteMapEnd()
+		{
+		}
+
+		public override void WriteListBegin(TList list)
+		{
+			WriteByte((byte)list.ElementType);
+			WriteI32(list.Count);
+		}
+
+		public override void WriteListEnd()
+		{
+		}
+
+		public override void WriteSetBegin(TSet set)
+		{
+			WriteByte((byte)set.ElementType);
+			WriteI32(set.Count);
+		}
+
+		public override void WriteSetEnd()
+		{
+		}
+
+		public override void WriteBool(bool b)
+		{
+			WriteByte(b ? (byte)1 : (byte)0);
+		}
+
+		private byte[] bout = new byte[1];
+		public override void WriteByte(byte b)
+		{
+			bout[0] = b;
+			trans.Write(bout, 0, 1);
+		}
+
+		private byte[] i16out = new byte[2];
+		public override void WriteI16(short s)
+		{
+			i16out[0] = (byte)(0xff & (s >> 8));
+			i16out[1] = (byte)(0xff & s);
+			trans.Write(i16out, 0, 2);
+		}
+
+		private byte[] i32out = new byte[4];
+		public override void WriteI32(int i32)
+		{
+			i32out[0] = (byte)(0xff & (i32 >> 24));
+			i32out[1] = (byte)(0xff & (i32 >> 16));
+			i32out[2] = (byte)(0xff & (i32 >> 8));
+			i32out[3] = (byte)(0xff & i32);
+			trans.Write(i32out, 0, 4);
+		}
+
+		private byte[] i64out = new byte[8];
+		public override void WriteI64(long i64)
+		{
+			i64out[0] = (byte)(0xff & (i64 >> 56));
+			i64out[1] = (byte)(0xff & (i64 >> 48));
+			i64out[2] = (byte)(0xff & (i64 >> 40));
+			i64out[3] = (byte)(0xff & (i64 >> 32));
+			i64out[4] = (byte)(0xff & (i64 >> 24));
+			i64out[5] = (byte)(0xff & (i64 >> 16));
+			i64out[6] = (byte)(0xff & (i64 >> 8));
+			i64out[7] = (byte)(0xff & i64);
+			trans.Write(i64out, 0, 8);
+		}
+
+		public override void WriteDouble(double d)
+		{
+			WriteI64(BitConverter.DoubleToInt64Bits(d));
+		}
+
+		public override void WriteString(string s)
+		{
+			byte[] b = Encoding.UTF8.GetBytes(s);
+			WriteI32(b.Length);
+			trans.Write(b, 0, b.Length);
+		}
+
+		#endregion
+
+		#region ReadMethods
+
+		public override TMessage ReadMessageBegin()
+		{
+			TMessage message = new TMessage();
+			int size = ReadI32();
+			if (size < 0)
+			{
+				uint version = (uint)size & VERSION_MASK;
+				if (version != VERSION_1)
+				{
+					throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version);
+				}
+				message.Type = (TMessageType)(size & 0x000000ff);
+				message.Name = ReadString();
+				message.SeqID = ReadI32();
+			}
+			else
+			{
+				if (strictRead_)
+				{
+					throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
+				}
+				message.Name = ReadStringBody(size);
+				message.Type = (TMessageType)ReadByte();
+				message.SeqID = ReadI32();
+			}
+			return message;
+		}
+
+		public override void ReadMessageEnd()
+		{
+		}
+
+		public override TStruct ReadStructBegin()
+		{
+			return new TStruct();
+		}
+
+		public override void ReadStructEnd()
+		{
+		}
+
+		public override TField ReadFieldBegin()
+		{
+			TField field = new TField();
+			field.Type = (TType)ReadByte();
+
+			if (field.Type != TType.Stop)
+			{
+				field.ID = ReadI16();
+			}
+
+			return field;
+		}
+
+		public override void ReadFieldEnd()
+		{
+		}
+
+		public override TMap ReadMapBegin()
+		{
+			TMap map = new TMap();
+			map.KeyType = (TType)ReadByte();
+			map.ValueType = (TType)ReadByte();
+			map.Count = ReadI32();
+
+			return map;
+		}
+
+		public override void ReadMapEnd()
+		{
+		}
+
+		public override TList ReadListBegin()
+		{
+			TList list = new TList();
+			list.ElementType = (TType)ReadByte();
+			list.Count = ReadI32();
+
+			return list;
+		}
+
+		public override void ReadListEnd()
+		{
+		}
+
+		public override TSet ReadSetBegin()
+		{
+			TSet set = new TSet();
+			set.ElementType = (TType)ReadByte();
+			set.Count = ReadI32();
+
+			return set;
+		}
+
+		public override void ReadSetEnd()
+		{
+		}
+
+		public override bool ReadBool()
+		{
+			return ReadByte() == 1;
+		}
+
+		private byte[] bin = new byte[1];
+		public override byte ReadByte()
+		{
+			ReadAll(bin, 0, 1);
+			return bin[0];
+		}
+
+		private byte[] i16in = new byte[2];
+		public override short ReadI16()
+		{
+			ReadAll(i16in, 0, 2);
+			return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff)));
+		}
+
+		private byte[] i32in = new byte[4];
+		public override int ReadI32()
+		{
+			ReadAll(i32in, 0, 4);
+			return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff)));
+		}
+
+		private byte[] i64in = new byte[8];
+		public override long ReadI64()
+		{
+			ReadAll(i64in, 0, 8);
+			return (long)(((long)(i64in[0] & 0xff) << 56) | ((long)(i64in[1] & 0xff) << 48) | ((long)(i64in[2] & 0xff) << 40) | ((long)(i64in[3] & 0xff) << 32) |
+				((long)(i64in[4] & 0xff) << 24) | ((long)(i64in[5] & 0xff) << 16) | ((long)(i64in[6] & 0xff) << 8) | ((long)(i64in[7] & 0xff)));
+		}
+
+		public override double ReadDouble()
+		{
+			return BitConverter.Int64BitsToDouble(ReadI64());
+		}
+
+		public void SetReadLength(int readLength)
+		{
+			readLength_ = readLength;
+			checkReadLength_ = true;
+		}
+
+		protected void CheckReadLength(int length)
+		{
+			if (checkReadLength_)
+			{
+				readLength_ -= length;
+				if (readLength_ < 0)
+				{
+					throw new Exception("Message length exceeded: " + length);
+				}
+			}
+		}
+
+		public override string ReadString()
+		{
+			int size = ReadI32();
+			return ReadStringBody(size);
+		}
+
+		public string ReadStringBody(int size)
+		{
+			CheckReadLength(size);
+			byte[] buf = new byte[size];
+			trans.ReadAll(buf, 0, size);
+			return Encoding.UTF8.GetString(buf);
+		}
+
+		private int ReadAll(byte[] buf, int off, int len)
+		{
+			CheckReadLength(len);
+			return trans.ReadAll(buf, off, len);
+		}
+
+		#endregion
+	}
+}
diff --git a/lib/csharp/src/Protocol/TField.cs b/lib/csharp/src/Protocol/TField.cs
new file mode 100644
index 0000000..f18381f
--- /dev/null
+++ b/lib/csharp/src/Protocol/TField.cs
@@ -0,0 +1,50 @@
+//
+//  TField.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TField
+	{
+		public TField()
+		{
+		}
+
+		public TField(string name, TType type, short id)
+		{
+			Name = name;
+			Type = type;
+			ID = id;
+		}
+
+		public string Name
+		{
+			get;
+			set;
+		}
+
+		public TType Type
+		{
+			get;
+			set;
+		}
+
+		public short ID
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TList.cs b/lib/csharp/src/Protocol/TList.cs
new file mode 100644
index 0000000..ff6aa53
--- /dev/null
+++ b/lib/csharp/src/Protocol/TList.cs
@@ -0,0 +1,43 @@
+//
+//  TList.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TList
+	{
+		public TList()
+		{
+		}
+
+		public TList(TType elementType, int count)
+		{
+			ElementType = elementType;
+			Count = count;
+		}
+
+		public TType ElementType
+		{
+			get;
+			set;
+		}
+
+		public int Count
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TMap.cs b/lib/csharp/src/Protocol/TMap.cs
new file mode 100644
index 0000000..495bf7c
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMap.cs
@@ -0,0 +1,50 @@
+//
+//  TMap.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TMap
+	{
+		public TMap()
+		{
+		}
+
+		public TMap(TType keyType, TType valueType, int count)
+		{
+			KeyType = keyType;
+			ValueType = valueType;
+			Count = count;
+		}
+
+		public TType KeyType
+		{
+			get;
+			set;
+		}
+
+		public TType ValueType
+		{
+			get;
+			set;
+		}
+
+		public int Count
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TMessage.cs b/lib/csharp/src/Protocol/TMessage.cs
new file mode 100644
index 0000000..60df660
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMessage.cs
@@ -0,0 +1,50 @@
+//
+//  TMessage.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TMessage
+	{
+		public TMessage()
+		{
+		}
+
+		public TMessage(string name, TMessageType type, int seqid)
+		{
+			Name = name;
+			Type = type;
+			SeqID = seqid;
+		}
+
+		public string Name
+		{
+			get;
+			set;
+		}
+
+		public TMessageType Type
+		{
+			get;
+			set;
+		}
+
+		public int SeqID
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TMessageType.cs b/lib/csharp/src/Protocol/TMessageType.cs
new file mode 100644
index 0000000..1cadf31
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMessageType.cs
@@ -0,0 +1,25 @@
+//
+//  TMessageType.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public enum TMessageType
+	{
+		Call = 1,
+		Reply = 2,
+		Exception = 3
+	}
+}
diff --git a/lib/csharp/src/Protocol/TProtocol.cs b/lib/csharp/src/Protocol/TProtocol.cs
new file mode 100644
index 0000000..f46b6d1
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocol.cs
@@ -0,0 +1,75 @@
+//
+//  TProtocol.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Transport;
+
+namespace Thrift.Protocol
+{
+	public abstract class TProtocol
+	{
+		protected TTransport trans;
+
+		protected TProtocol(TTransport trans)
+		{
+			this.trans = trans;
+		}
+
+		public TTransport Transport
+		{
+			get { return trans; }
+		}
+
+		public abstract void WriteMessageBegin(TMessage message);
+		public abstract void WriteMessageEnd();
+		public abstract void WriteStructBegin(TStruct struc);
+		public abstract void WriteStructEnd();
+		public abstract void WriteFieldBegin(TField field);
+		public abstract void WriteFieldEnd();
+		public abstract void WriteFieldStop();
+		public abstract void WriteMapBegin(TMap map);
+		public abstract void WriteMapEnd();
+		public abstract void WriteListBegin(TList list);
+		public abstract void WriteListEnd();
+		public abstract void WriteSetBegin(TSet set);
+		public abstract void WriteSetEnd();
+		public abstract void WriteBool(bool b);
+		public abstract void WriteByte(byte b);
+		public abstract void WriteI16(short i16);
+		public abstract void WriteI32(int i32);
+		public abstract void WriteI64(long i64);
+		public abstract void WriteDouble(double d);
+		public abstract void WriteString(string s);
+
+		public abstract TMessage ReadMessageBegin();
+		public abstract void ReadMessageEnd();
+		public abstract TStruct ReadStructBegin();
+		public abstract void ReadStructEnd();
+		public abstract TField ReadFieldBegin();
+		public abstract void ReadFieldEnd();
+		public abstract TMap ReadMapBegin();
+		public abstract void ReadMapEnd();
+		public abstract TList ReadListBegin();
+		public abstract void ReadListEnd();
+		public abstract TSet ReadSetBegin();
+		public abstract void ReadSetEnd();
+		public abstract bool ReadBool();
+		public abstract byte ReadByte();
+		public abstract short ReadI16();
+		public abstract int ReadI32();
+		public abstract long ReadI64();
+		public abstract double ReadDouble();
+		public abstract string ReadString();
+	}
+}
diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs
new file mode 100644
index 0000000..0941a81
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolException.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	class TProtocolException : Exception
+	{
+		public const int UNKNOWN = 0;
+		public const int INVALID_DATA = 1;
+		public const int NEGATIVE_SIZE = 2;
+		public const int SIZE_LIMIT = 3;
+		public const int BAD_VERSION = 4;
+
+		protected int type_ = UNKNOWN;
+
+		public TProtocolException()
+			: base()
+		{
+		}
+
+		public TProtocolException(int type)
+			: base()
+		{
+			type_ = type;
+		}
+
+		public TProtocolException(int type, String message)
+			: base(message)
+		{
+			type_ = type;
+		}
+
+		public TProtocolException(String message)
+			: base(message)
+		{
+		}
+
+		public int getType()
+		{
+			return type_;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TProtocolFactory.cs b/lib/csharp/src/Protocol/TProtocolFactory.cs
new file mode 100644
index 0000000..5434da9
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolFactory.cs
@@ -0,0 +1,23 @@
+//
+//  TProtocolFactory.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Transport;
+
+namespace Thrift.Protocol
+{
+	public interface TProtocolFactory
+	{
+		TProtocol GetProtocol(TTransport trans);
+	}
+}
diff --git a/lib/csharp/src/Protocol/TProtocolUtil.cs b/lib/csharp/src/Protocol/TProtocolUtil.cs
new file mode 100644
index 0000000..67f0ce6
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolUtil.cs
@@ -0,0 +1,88 @@
+//
+//  TProtocolUtil.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public static class TProtocolUtil
+	{
+		public static void Skip(TProtocol prot, TType type)
+		{
+			switch (type)
+			{
+				case TType.Bool:
+					prot.ReadBool();
+					break;
+				case TType.Byte:
+					prot.ReadByte();
+					break;
+				case TType.I16:
+					prot.ReadI16();
+					break;
+				case TType.I32:
+					prot.ReadI32();
+					break;
+				case TType.I64:
+					prot.ReadI64();
+					break;
+				case TType.Double:
+					prot.ReadDouble();
+					break;
+				case TType.String:
+					prot.ReadString();
+					break;
+				case TType.Struct:
+					prot.ReadStructBegin();
+					while (true)
+					{
+						TField field = prot.ReadFieldBegin();
+						if (field.Type == TType.Stop)
+						{
+							break;
+						}
+						Skip(prot, field.Type);
+						prot.ReadFieldEnd();
+					}
+					prot.ReadStructEnd();
+					break;
+				case TType.Map:
+					TMap map = prot.ReadMapBegin();
+					for (int i = 0; i < map.Count; i++)
+					{
+						Skip(prot, map.KeyType);
+						Skip(prot, map.ValueType);
+					}
+					prot.ReadMapEnd();
+					break;
+				case TType.Set:
+					TSet set = prot.ReadSetBegin();
+					for (int i = 0; i < set.Count; i++)
+					{
+						Skip(prot, set.ElementType);
+					}
+					prot.ReadSetEnd();
+					break;
+				case TType.List:
+					TList list = prot.ReadListBegin();
+					for (int i = 0; i < list.Count; i++)
+					{
+						Skip(prot, list.ElementType);
+					}
+					prot.ReadListEnd();
+					break;
+			}
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TSet.cs b/lib/csharp/src/Protocol/TSet.cs
new file mode 100644
index 0000000..c4c6fc3
--- /dev/null
+++ b/lib/csharp/src/Protocol/TSet.cs
@@ -0,0 +1,43 @@
+//
+//  TSet.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TSet
+	{
+		public TSet()
+		{
+		}
+
+		public TSet(TType elementType, int count)
+		{
+			ElementType = elementType;
+			Count = count;
+		}
+
+		public TType ElementType
+		{
+			get;
+			set;
+		}
+
+		public int Count
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TStruct.cs b/lib/csharp/src/Protocol/TStruct.cs
new file mode 100644
index 0000000..88f12df
--- /dev/null
+++ b/lib/csharp/src/Protocol/TStruct.cs
@@ -0,0 +1,35 @@
+//
+//  TStruct.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public class TStruct
+	{
+		public TStruct()
+		{
+		}
+
+		public TStruct(string name)
+		{
+			Name = name;
+		}
+
+		public string Name
+		{
+			get;
+			set;
+		}
+	}
+}
diff --git a/lib/csharp/src/Protocol/TType.cs b/lib/csharp/src/Protocol/TType.cs
new file mode 100644
index 0000000..0badb33
--- /dev/null
+++ b/lib/csharp/src/Protocol/TType.cs
@@ -0,0 +1,35 @@
+//
+//  TType.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+	public enum TType : byte
+	{
+		Stop = 0,
+		Void = 1,
+		Bool = 2,
+		Byte = 3,
+		Double = 4,
+		I16 = 6,
+		I32 = 8,
+		I64 = 10,
+		String = 11,
+		Struct = 12,
+		Map = 13,
+		Set = 14,
+		List = 15
+	}
+}
diff --git a/lib/csharp/src/Server/TServer.cs b/lib/csharp/src/Server/TServer.cs
new file mode 100644
index 0000000..3e70b11
--- /dev/null
+++ b/lib/csharp/src/Server/TServer.cs
@@ -0,0 +1,108 @@
+//
+//  TServer.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using Thrift.Protocol;
+using Thrift.Transport;
+
+namespace Thrift.Server
+{
+	public abstract class TServer
+	{
+		/**
+		 * Core processor
+		 */
+		protected TProcessor processor;
+
+		/**
+		 * Server transport
+		 */
+		protected TServerTransport serverTransport;
+
+		/**
+		 * Input Transport Factory
+		 */
+		protected TTransportFactory inputTransportFactory;
+
+		/**
+		 * Output Transport Factory
+		 */
+		protected TTransportFactory outputTransportFactory;
+
+		/**
+		 * Input Protocol Factory
+		 */
+		protected TProtocolFactory inputProtocolFactory;
+
+		/**
+		 * Output Protocol Factory
+		 */
+		protected TProtocolFactory outputProtocolFactory;
+
+		/**
+		 * Default constructors.
+		 */
+
+		public TServer(TProcessor processor,
+						  TServerTransport serverTransport)
+			:this(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory())
+		{
+		}
+
+		public TServer(TProcessor processor,
+						  TServerTransport serverTransport,
+						  TTransportFactory transportFactory)
+			:this(processor,
+				 serverTransport,
+				 transportFactory,
+				 transportFactory,
+				 new TBinaryProtocol.Factory(),
+				 new TBinaryProtocol.Factory())
+		{
+		}
+
+		public TServer(TProcessor processor,
+						  TServerTransport serverTransport,
+						  TTransportFactory transportFactory,
+						  TProtocolFactory protocolFactory)
+			:this(processor,
+				 serverTransport,
+				 transportFactory,
+				 transportFactory,
+				 protocolFactory,
+				 protocolFactory)
+		{
+		}
+
+		public TServer(TProcessor processor,
+						  TServerTransport serverTransport,
+						  TTransportFactory inputTransportFactory,
+						  TTransportFactory outputTransportFactory,
+						  TProtocolFactory inputProtocolFactory,
+						  TProtocolFactory outputProtocolFactory)
+		{
+			this.processor = processor;
+			this.serverTransport = serverTransport;
+			this.inputTransportFactory = inputTransportFactory;
+			this.outputTransportFactory = outputTransportFactory;
+			this.inputProtocolFactory = inputProtocolFactory;
+			this.outputProtocolFactory = outputProtocolFactory;
+		}
+
+		/**
+		 * The run method fires up the server and gets things going.
+		 */
+		public abstract void Serve();
+	}
+}
+
diff --git a/lib/csharp/src/Server/TSimpleServer.cs b/lib/csharp/src/Server/TSimpleServer.cs
new file mode 100644
index 0000000..c3461ef
--- /dev/null
+++ b/lib/csharp/src/Server/TSimpleServer.cs
@@ -0,0 +1,108 @@
+//
+//  TSimpleServer.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Transport;
+using Thrift.Protocol;
+
+namespace Thrift.Server
+{
+	/// <summary>
+	/// Simple single-threaded server for testing
+	/// </summary>
+	class TSimpleServer : TServer
+	{
+		public TSimpleServer(TProcessor processor,
+						  TServerTransport serverTransport)
+			:base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory())
+		{
+		}
+
+		public TSimpleServer(TProcessor processor,
+						  TServerTransport serverTransport,
+						  TTransportFactory transportFactory)
+			:base(processor,
+				 serverTransport,
+				 transportFactory,
+				 transportFactory,
+				 new TBinaryProtocol.Factory(),
+				 new TBinaryProtocol.Factory())
+		{
+		}
+
+		public TSimpleServer(TProcessor processor,
+						  TServerTransport serverTransport,
+						  TTransportFactory transportFactory,
+						  TProtocolFactory protocolFactory)
+			:base(processor,
+				 serverTransport,
+				 transportFactory,
+				 transportFactory,
+				 protocolFactory,
+				 protocolFactory)
+		{
+		}
+
+		public override void Serve()
+		{
+			try
+			{
+				serverTransport.Listen();
+			}
+			catch (TTransportException ttx)
+			{
+				Console.Error.WriteLine(ttx);
+				return;
+			}
+
+			while (true)
+			{
+				TTransport client = null;
+				TTransport inputTransport = null;
+				TTransport outputTransport = null;
+				TProtocol inputProtocol = null;
+				TProtocol outputProtocol = null;
+				try
+				{
+					client = serverTransport.Accept();
+					if (client != null)
+					{
+						inputTransport = inputTransportFactory.GetTransport(client);
+						outputTransport = outputTransportFactory.GetTransport(client);
+						inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+						outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+						while (processor.Process(inputProtocol, outputProtocol)) { }
+					}
+				}
+				catch (TTransportException ttx)
+				{
+					// Client died, just move on
+				}
+				catch (Exception x)
+				{
+					Console.Error.WriteLine(x);
+				}
+
+				if (inputTransport != null)
+				{
+					inputTransport.Close();
+				}
+
+				if (outputTransport != null)
+				{
+					outputTransport.Close();
+				}
+			}
+		}
+	}
+}
diff --git a/lib/csharp/src/Server/TThreadPoolServer.cs b/lib/csharp/src/Server/TThreadPoolServer.cs
new file mode 100644
index 0000000..c42d348
--- /dev/null
+++ b/lib/csharp/src/Server/TThreadPoolServer.cs
@@ -0,0 +1,143 @@
+//
+//  TThreadPoolServer.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using Thrift.Protocol;
+using Thrift.Transport;
+
+namespace Thrift.Server
+{
+	/// <summary>
+	/// Server that uses C# built-in ThreadPool to spawn threads when handling requests
+	/// </summary>
+	public class TThreadPoolServer : TServer
+	{
+		private const int DEFAULT_MIN_THREADS = 10;
+		private const int DEFAULT_MAX_THREADS = 100;
+
+		public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
+			:this(processor, serverTransport,
+				 new TTransportFactory(), new TTransportFactory(),
+				 new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+				 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS)
+		{
+		}
+
+		public TThreadPoolServer(TProcessor processor,
+								 TServerTransport serverTransport,
+								 TTransportFactory transportFactory,
+								 TProtocolFactory protocolFactory)
+			:this(processor, serverTransport,
+				 transportFactory, transportFactory,
+				 protocolFactory, protocolFactory,
+				 DEFAULT_MIN_THREADS, DEFAULT_MAX_THREADS)
+		{
+		}
+
+		public TThreadPoolServer(TProcessor processor,
+								 TServerTransport serverTransport,
+								 TTransportFactory inputTransportFactory,
+								 TTransportFactory outputTransportFactory,
+								 TProtocolFactory inputProtocolFactory,
+								 TProtocolFactory outputProtocolFactory,
+								 int minThreadPoolThreads, int maxThreadPoolThreads)
+			:base(processor, serverTransport, inputTransportFactory, outputTransportFactory,
+				  inputProtocolFactory, outputProtocolFactory)
+		{
+			if (!ThreadPool.SetMinThreads(minThreadPoolThreads, minThreadPoolThreads))
+			{
+				throw new Exception("Error: could not SetMinThreads in ThreadPool");
+			}
+			if (!ThreadPool.SetMaxThreads(maxThreadPoolThreads, maxThreadPoolThreads))
+			{
+				throw new Exception("Error: could not SetMaxThreads in ThreadPool");
+			}
+
+		}
+
+		/// <summary>
+		/// Use new ThreadPool thread for each new client connection
+		/// </summary>
+		public override void Serve()
+		{
+			try
+			{
+				serverTransport.Listen();
+			}
+			catch (TTransportException ttx)
+			{
+				Console.Error.WriteLine("Error, could not listen on ServerTransport: " + ttx);
+				return;
+			}
+
+			while (true)
+			{
+				int failureCount = 0;
+				try
+				{
+					TTransport client = serverTransport.Accept();
+					ThreadPool.QueueUserWorkItem(this.Execute, client);
+				}
+				catch (TTransportException ttx)
+				{
+					++failureCount;
+					Console.Error.WriteLine(ttx);
+				}
+			}
+		}
+
+		/// <summary>
+		/// Loops on processing a client forever
+		/// threadContext will be a TTransport instance
+		/// </summary>
+		/// <param name="threadContext"></param>
+		private void Execute(Object threadContext)
+		{
+			TTransport client = (TTransport)threadContext;
+			TTransport inputTransport = null;
+			TTransport outputTransport = null;
+			TProtocol inputProtocol = null;
+			TProtocol outputProtocol = null;
+			try
+			{
+				inputTransport = inputTransportFactory.GetTransport(client);
+				outputTransport = outputTransportFactory.GetTransport(client);
+				inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+				outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+				while (processor.Process(inputProtocol, outputProtocol)) 
+				{
+					//keep processing requests until client disconnects
+				}
+			}
+			catch (TTransportException ttx)
+			{
+				// Assume the client died and continue silently
+			}
+			
+			catch (Exception x)
+			{
+				Console.Error.WriteLine("Error: " + x);
+			}
+
+			if (inputTransport != null)
+			{
+				inputTransport.Close();
+			}
+			if (outputTransport != null)
+			{
+				outputTransport.Close();
+			}
+		}
+	}
+}
diff --git a/lib/csharp/src/TApplicationException.cs b/lib/csharp/src/TApplicationException.cs
new file mode 100644
index 0000000..e4f3acf
--- /dev/null
+++ b/lib/csharp/src/TApplicationException.cs
@@ -0,0 +1,127 @@
+//
+//  TApplicationException.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Protocol;
+
+namespace Thrift
+{
+	public class TApplicationException : Exception
+	{
+		protected ExceptionType type;
+
+		public TApplicationException()
+		{
+		}
+
+		public TApplicationException(ExceptionType type)
+		{
+			this.type = type;
+		}
+
+		public TApplicationException(ExceptionType type, string message)
+			: base(message)
+		{
+			this.type = type;
+		}
+
+		public static TApplicationException Read(TProtocol iprot)
+		{
+			TField field;
+			TStruct struc = iprot.ReadStructBegin();
+
+			string message = null;
+			ExceptionType type = ExceptionType.Unknown;
+
+			while (true)
+			{
+				field = iprot.ReadFieldBegin();
+				if (field.Type == TType.Stop)
+				{
+					break;
+				}
+
+				switch (field.ID)
+				{
+					case 1:
+						if (field.Type == TType.String)
+						{
+							message = iprot.ReadString();
+						}
+						else
+						{
+							TProtocolUtil.Skip(iprot, field.Type);
+						}
+						break;
+					case 2:
+						if (field.Type == TType.I32)
+						{
+							type = (ExceptionType)iprot.ReadI32();
+						}
+						else
+						{
+							TProtocolUtil.Skip(iprot, field.Type);
+						}
+						break;
+					default:
+						TProtocolUtil.Skip(iprot, field.Type);
+						break;
+				}
+
+				iprot.ReadFieldEnd();
+			}
+
+			iprot.ReadStructEnd();
+
+			return new TApplicationException(type, message);
+		}
+
+		public void Write(TProtocol oprot)
+		{
+			TStruct struc = new TStruct("TApplicationException");
+			TField field = new TField();
+
+			oprot.WriteStructBegin(struc);
+
+			if (!String.IsNullOrEmpty(Message))
+			{
+				field.Name = "message";
+				field.Type = TType.String;
+				field.ID = 1;
+				oprot.WriteFieldBegin(field);
+				oprot.WriteString(Message);
+				oprot.WriteFieldEnd();
+			}
+
+			field.Name = "type";
+			field.Type = TType.I32;
+			field.ID = 2;
+			oprot.WriteFieldBegin(field);
+			oprot.WriteI32((int)type);
+			oprot.WriteFieldEnd();
+			oprot.WriteFieldStop();
+			oprot.WriteStructEnd();
+		}
+
+		public enum ExceptionType
+		{
+			Unknown,
+			UnknownMethod,
+			InvalidMessageType,
+			WrongMethodName,
+			BadSequenceID,
+			MissingResult
+		}
+	}
+}
diff --git a/lib/csharp/src/TProcessor.cs b/lib/csharp/src/TProcessor.cs
new file mode 100644
index 0000000..7567820
--- /dev/null
+++ b/lib/csharp/src/TProcessor.cs
@@ -0,0 +1,24 @@
+//
+//  TProcessor.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Distributed under the Thrift Software License
+//
+//  See accompanying file LICENSE or visit the Thrift site at:
+//  http://developers.facebook.com/thrift/using
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Thrift.Protocol;
+
+namespace Thrift
+{
+	public interface TProcessor
+	{
+		bool Process(TProtocol iprot, TProtocol oprot);
+	}
+}
diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj
new file mode 100644
index 0000000..4b407b1
--- /dev/null
+++ b/lib/csharp/src/Thrift.csproj
@@ -0,0 +1,79 @@
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{499EB63C-D74C-47E8-AE48-A2FC94538E9D}</ProjectGuid>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>Library</OutputType>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>Thrift</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <RootNamespace>Thrift</RootNamespace>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Linq" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Protocol\TBinaryProtocol.cs" />
+    <Compile Include="Protocol\TField.cs" />
+    <Compile Include="Protocol\TList.cs" />
+    <Compile Include="Protocol\TMap.cs" />
+    <Compile Include="Protocol\TMessage.cs" />
+    <Compile Include="Protocol\TMessageType.cs" />
+    <Compile Include="Protocol\TProtocol.cs" />
+    <Compile Include="Protocol\TProtocolException.cs" />
+    <Compile Include="Protocol\TProtocolFactory.cs" />
+    <Compile Include="Protocol\TProtocolUtil.cs" />
+    <Compile Include="Protocol\TSet.cs" />
+    <Compile Include="Protocol\TStruct.cs" />
+    <Compile Include="Protocol\TType.cs" />
+    <Compile Include="Server\TServer.cs" />
+    <Compile Include="Server\TSimpleServer.cs" />
+    <Compile Include="Server\TThreadPoolServer.cs" />
+    <Compile Include="TApplicationException.cs" />
+    <Compile Include="TProcessor.cs" />
+    <Compile Include="Transport\TServerSocket.cs" />
+    <Compile Include="Transport\TServerTransport.cs" />
+    <Compile Include="Transport\TSocket.cs" />
+    <Compile Include="Transport\TStreamTransport.cs" />
+    <Compile Include="Transport\TTransport.cs" />
+    <Compile Include="Transport\TTransportException.cs" />
+    <Compile Include="Transport\TTransportFactory.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+  <ProjectExtensions>
+    <VisualStudio AllowExistingFolder="true" />
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
diff --git a/lib/csharp/src/Thrift.sln b/lib/csharp/src/Thrift.sln
new file mode 100644
index 0000000..cb7342c
--- /dev/null
+++ b/lib/csharp/src/Thrift.sln
@@ -0,0 +1,51 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "..\..\..\test\csharp\ThriftTest\ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}"
+	ProjectSection(ProjectDependencies) = postProject
+		{499EB63C-D74C-47E8-AE48-A2FC94538E9D} = {499EB63C-D74C-47E8-AE48-A2FC94538E9D}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMSBuildTask", "..\ThriftMSBuildTask\ThriftMSBuildTask.csproj", "{EC0A0231-66EA-4593-A792-C6CA3BB8668E}"
+EndProject
+Global
+	GlobalSection(SourceCodeControl) = preSolution
+		SccNumberOfProjects = 4
+		SccProjectName0 = Perforce\u0020Project
+		SccLocalPath0 = ..\\..\\..
+		SccProvider0 = MSSCCI:Perforce\u0020SCM
+		SccProjectFilePathRelativizedFromConnection0 = lib\\csharp\\src\\
+		SccProjectUniqueName1 = Thrift.csproj
+		SccLocalPath1 = ..\\..\\..
+		SccProjectFilePathRelativizedFromConnection1 = lib\\csharp\\src\\
+		SccProjectUniqueName2 = ..\\..\\..\\test\\csharp\\ThriftTest\\ThriftTest.csproj
+		SccLocalPath2 = ..\\..\\..
+		SccProjectFilePathRelativizedFromConnection2 = test\\csharp\\ThriftTest\\
+		SccProjectUniqueName3 = ..\\ThriftMSBuildTask\\ThriftMSBuildTask.csproj
+		SccLocalPath3 = ..\\..\\..
+		SccProjectFilePathRelativizedFromConnection3 = lib\\csharp\\ThriftMSBuildTask\\
+	EndGlobalSection
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.Build.0 = Release|Any CPU
+		{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/lib/csharp/src/Transport/TServerSocket.cs b/lib/csharp/src/Transport/TServerSocket.cs
new file mode 100644
index 0000000..cb4a84f
--- /dev/null
+++ b/lib/csharp/src/Transport/TServerSocket.cs
@@ -0,0 +1,131 @@
+//
+//  TServerTransport.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Net.Sockets;
+
+
+namespace Thrift.Transport
+{
+	public class TServerSocket : TServerTransport
+	{
+		/**
+		* Underlying server with socket
+		*/
+		private TcpListener server = null;
+
+		/**
+		 * Port to listen on
+		 */
+		private int port = 0;
+
+		/**
+		 * Timeout for client sockets from accept
+		 */
+		private int clientTimeout = 0;
+
+		/**
+		 * Creates a server socket from underlying socket object
+		 */
+		public TServerSocket(TcpListener listener)
+			:this(listener, 0)
+		{
+		}
+
+		/**
+		 * Creates a server socket from underlying socket object
+		 */
+		public TServerSocket(TcpListener listener, int clientTimeout)
+		{
+			this.server = listener;
+			this.clientTimeout = clientTimeout;
+		}
+
+		/**
+		 * Creates just a port listening server socket
+		 */
+		public TServerSocket(int port)
+			: this(port, 0)
+		{
+		}
+
+		/**
+		 * Creates just a port listening server socket
+		 */
+		public TServerSocket(int port, int clientTimeout)
+		{
+			this.port = port;
+			this.clientTimeout = clientTimeout;
+			try
+			{
+				// Make server socket
+				server = new TcpListener(System.Net.IPAddress.Any, this.port);
+			}
+			catch (Exception e)
+			{
+				server = null;
+				throw new TTransportException("Could not create ServerSocket on port " + port + ".");
+			}
+		}
+
+		public override void Listen()
+		{
+			// Make sure not to block on accept
+			if (server != null)
+			{
+				try
+				{
+					server.Start();
+				}
+				catch (SocketException sx)
+				{
+					Console.Error.WriteLine(sx);
+				}
+			}
+		}
+
+		protected override TTransport AcceptImpl()
+		{
+			if (server == null)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
+			}
+			try
+			{
+				TcpClient result = server.AcceptTcpClient();
+				TSocket result2 = new TSocket(result);
+				result2.Timeout = clientTimeout;
+				return result2;
+			}
+			catch (Exception ex)
+			{
+				throw new TTransportException(ex.ToString());
+			}
+		}
+
+		public override void Close()
+		{
+			if (server != null)
+			{
+				try
+				{
+					server.Stop();
+				}
+				catch (Exception ex)
+				{
+					Console.Error.WriteLine("WARNING: Could not close server socket: " + ex);
+				}
+				server = null;
+			}
+		}
+	}
+}
diff --git a/lib/csharp/src/Transport/TServerTransport.cs b/lib/csharp/src/Transport/TServerTransport.cs
new file mode 100644
index 0000000..b4f5f07
--- /dev/null
+++ b/lib/csharp/src/Transport/TServerTransport.cs
@@ -0,0 +1,31 @@
+//
+//  TServerTransport.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Transport
+{
+	public abstract class TServerTransport
+	{
+		public abstract void Listen();
+		public abstract void Close();
+		protected abstract TTransport AcceptImpl();
+
+		public TTransport Accept()
+		{
+			TTransport transport = AcceptImpl();
+			if (transport == null) {
+			  throw new TTransportException("accept() may not return NULL");
+			}
+			return transport;
+		 }
+	}
+}
diff --git a/lib/csharp/src/Transport/TSocket.cs b/lib/csharp/src/Transport/TSocket.cs
new file mode 100644
index 0000000..c05d587
--- /dev/null
+++ b/lib/csharp/src/Transport/TSocket.cs
@@ -0,0 +1,122 @@
+//
+//  TSocket.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Net.Sockets;
+
+namespace Thrift.Transport
+{
+	public class TSocket : TStreamTransport
+	{
+		private TcpClient client = null;
+		private string host = null;
+		private int port = 0;
+		private int timeout = 0;
+
+		public TSocket(TcpClient client)
+		{
+			this.client = client;
+
+			if (IsOpen)
+			{
+				inputStream = client.GetStream();
+				outputStream = client.GetStream();
+			}
+		}
+
+		public TSocket(string host, int port) : this(host, port, 0)
+		{
+		}
+
+		public TSocket(string host, int port, int timeout)
+		{
+			this.host = host;
+			this.port = port;
+			this.timeout = timeout;
+
+			InitSocket();
+		}
+
+		private void InitSocket()
+		{
+			client = new TcpClient();
+			client.ReceiveTimeout = client.SendTimeout = timeout;
+		}
+
+		public int Timeout
+		{
+			set
+			{
+				client.ReceiveTimeout = client.SendTimeout = timeout = value;
+			}
+		}
+
+		public TcpClient TcpClient
+		{
+			get
+			{
+				return client;
+			}
+		}
+
+		public override bool IsOpen
+		{
+			get
+			{
+				if (client == null)
+				{
+					return false;
+				}
+
+				return client.Connected;
+			}
+		}
+
+		public override void Open()
+		{
+			if (IsOpen)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
+			}
+
+			if (String.IsNullOrEmpty(host))
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
+			}
+
+			if (port <= 0)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
+			}
+
+			if (client == null)
+			{
+				InitSocket();
+			}
+
+			client.Connect(host, port);
+			inputStream = client.GetStream();
+			outputStream = client.GetStream();
+		}
+
+		public override void Close()
+		{
+			base.Close();
+			if (client != null)
+			{
+				client.Close();
+				client = null;
+			}
+		}
+	}
+}
diff --git a/lib/csharp/src/Transport/TStreamTransport.cs b/lib/csharp/src/Transport/TStreamTransport.cs
new file mode 100644
index 0000000..1715b6a
--- /dev/null
+++ b/lib/csharp/src/Transport/TStreamTransport.cs
@@ -0,0 +1,87 @@
+//
+//  TStreamTransport.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace Thrift.Transport
+{
+	public class TStreamTransport : TTransport
+	{
+		protected Stream inputStream;
+		protected Stream outputStream;
+
+		public TStreamTransport()
+		{
+		}
+
+		public TStreamTransport(Stream inputStream, Stream outputStream)
+		{
+			this.inputStream = inputStream;
+			this.outputStream = outputStream;
+		}
+
+		public override bool IsOpen
+		{
+			get { return true; }
+		}
+
+		public override void Open()
+		{
+		}
+
+		public override void Close()
+		{
+			if (inputStream != null)
+			{
+				inputStream.Close();
+				inputStream = null;
+			}
+			if (outputStream != null)
+			{
+				outputStream.Close();
+				outputStream = null;
+			}
+		}
+
+		public override int Read(byte[] buf, int off, int len)
+		{
+			if (inputStream == null)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot read from null inputstream");
+			}
+
+			return inputStream.Read(buf, off, len);
+		}
+
+		public override void Write(byte[] buf, int off, int len)
+		{
+			if (outputStream == null)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot write to null outputstream");
+			}
+
+			outputStream.Write(buf, off, len);
+		}
+
+		public override void Flush()
+		{
+			if (outputStream == null)
+			{
+				throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot flush null outputstream");
+			}
+
+			outputStream.Flush();
+		}
+	}
+}
diff --git a/lib/csharp/src/Transport/TTransport.cs b/lib/csharp/src/Transport/TTransport.cs
new file mode 100644
index 0000000..90f7e74
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransport.cs
@@ -0,0 +1,60 @@
+//
+//  TTransport.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Transport
+{
+	public abstract class TTransport
+	{
+		public abstract bool IsOpen
+		{
+			get;
+		}
+
+		public bool Peek()
+		{
+			return IsOpen;
+		}
+
+		public abstract void Open();
+
+		public abstract void Close();
+
+		public abstract int Read(byte[] buf, int off, int len);
+
+		public int ReadAll(byte[] buf, int off, int len)
+		{
+			int got = 0;
+			int ret = 0;
+
+			while (got < len)
+			{
+				ret = Read(buf, off + got, len - got);
+				if (ret <= 0)
+				{
+					throw new TTransportException("Cannot read, Remote side has closed");
+				}
+				got += ret;
+			}
+
+			return got;
+		}
+
+		public abstract void Write(byte[] buf, int off, int len);
+
+		public virtual void Flush()
+		{
+		}
+	}
+}
diff --git a/lib/csharp/src/Transport/TTransportException.cs b/lib/csharp/src/Transport/TTransportException.cs
new file mode 100644
index 0000000..d59c46e
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransportException.cs
@@ -0,0 +1,58 @@
+//
+//  TTransportException.cs
+//
+//  Begin:  Aug 19, 2007
+//  Authors: 
+//		Todd Berman <tberman@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Transport
+{
+	public class TTransportException : Exception
+	{
+		protected ExceptionType type;
+
+		public TTransportException()
+			: base()
+		{
+		}
+
+		public TTransportException(ExceptionType type)
+			: this()
+		{
+			this.type = type;
+		}
+
+		public TTransportException(ExceptionType type, string message)
+			: base(message)
+		{
+			this.type = type;
+		}
+
+		public TTransportException(string message)
+			: base(message)
+		{
+		}
+
+		public ExceptionType Type
+		{
+			get { return type; }
+		}
+
+		public enum ExceptionType
+		{
+			Unknown,
+			NotOpen,
+			AlreadyOpen,
+			TimedOut,
+			EndOfFile
+		}
+	}
+}
diff --git a/lib/csharp/src/Transport/TTransportFactory.cs b/lib/csharp/src/Transport/TTransportFactory.cs
new file mode 100644
index 0000000..456140d
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransportFactory.cs
@@ -0,0 +1,32 @@
+//
+//  TTransportFactory.cs
+//
+//  Begin:  Dec 3, 2007
+//  Authors: 
+//		Will Palmeri <wpalmeri@imeem.com>
+//
+//  Copyright (C) 2007 imeem, inc. <http://www.imeem.com>
+//  All rights reserved.
+//
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+
+namespace Thrift.Transport
+{
+	/// <summary>
+	/// From Mark Slee & Aditya Agarwal of Facebook:
+	/// Factory class used to create wrapped instance of Transports.
+	/// This is used primarily in servers, which get Transports from
+	/// a ServerTransport and then may want to mutate them (i.e. create
+	/// a BufferedTransport from the underlying base transport)
+	/// </summary>
+	public class TTransportFactory
+	{
+		public TTransport GetTransport(TTransport trans)
+		{
+			return trans;
+		}
+	}
+}