Revert "THRIFT-4982 Remove deprecated C# bindings from the code base"

Only compiler, test, lib and tutorial code.
diff --git a/lib/csharp/src/Collections/TCollections.cs b/lib/csharp/src/Collections/TCollections.cs
new file mode 100644
index 0000000..84afb6a
--- /dev/null
+++ b/lib/csharp/src/Collections/TCollections.cs
@@ -0,0 +1,94 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+using System;
+using System.Collections;
+
+namespace Thrift.Collections
+{
+    public class TCollections
+    {
+        /// <summary>
+        /// This will return true if the two collections are value-wise the same.
+        /// If the collection contains a collection, the collections will be compared using this method.
+        /// </summary>
+        public static bool Equals (IEnumerable first, IEnumerable second)
+        {
+            if (first == null && second == null)
+            {
+                return true;
+            }
+            if (first == null || second == null)
+            {
+                return false;
+            }
+            IEnumerator fiter = first.GetEnumerator ();
+            IEnumerator siter = second.GetEnumerator ();
+
+            bool fnext = fiter.MoveNext ();
+            bool snext = siter.MoveNext ();
+            while (fnext && snext)
+            {
+                IEnumerable fenum = fiter.Current as IEnumerable;
+                IEnumerable senum = siter.Current as IEnumerable;
+                if (fenum != null && senum != null)
+                {
+                    if (!Equals(fenum, senum))
+                    {
+                        return false;
+                    }
+                }
+                else if (fenum == null ^ senum == null)
+                {
+                    return false;
+                }
+                else if (!Equals(fiter.Current, siter.Current))
+                {
+                    return false;
+                }
+                fnext = fiter.MoveNext();
+                snext = siter.MoveNext();
+            }
+
+            return fnext == snext;
+        }
+
+        /// <summary>
+        /// This returns a hashcode based on the value of the enumerable.
+        /// </summary>
+        public static int GetHashCode (IEnumerable enumerable)
+        {
+            if (enumerable == null)
+            {
+                return 0;
+            }
+
+            int hashcode = 0;
+            foreach (object obj in enumerable)
+            {
+                IEnumerable enum2 = obj as IEnumerable;
+                int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2);
+                unchecked
+                {
+                    hashcode = (hashcode * 397) ^ (objHash);
+                }
+            }
+            return hashcode;
+        }
+    }
+}
diff --git a/lib/csharp/src/Collections/THashSet.cs b/lib/csharp/src/Collections/THashSet.cs
new file mode 100644
index 0000000..e29271a
--- /dev/null
+++ b/lib/csharp/src/Collections/THashSet.cs
@@ -0,0 +1,160 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+#if SILVERLIGHT
+using System.Runtime.Serialization;
+#endif
+
+namespace Thrift.Collections
+{
+#if SILVERLIGHT
+    [DataContract]
+#else
+    [Serializable]
+#endif
+    public class THashSet<T> : ICollection<T>
+    {
+#if NET_2_0 || SILVERLIGHT
+#if SILVERLIGHT
+        [DataMember]
+#endif
+        TDictSet<T> set = new TDictSet<T>();
+#else
+        HashSet<T> set = new HashSet<T>();
+#endif
+        public int Count
+        {
+            get { return set.Count; }
+        }
+
+        public bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public void Add(T item)
+        {
+            set.Add(item);
+        }
+
+        public void Clear()
+        {
+            set.Clear();
+        }
+
+        public bool Contains(T item)
+        {
+            return set.Contains(item);
+        }
+
+        public void CopyTo(T[] array, int arrayIndex)
+        {
+            set.CopyTo(array, arrayIndex);
+        }
+
+        public IEnumerator GetEnumerator()
+        {
+            return set.GetEnumerator();
+        }
+
+        IEnumerator<T> IEnumerable<T>.GetEnumerator()
+        {
+            return ((IEnumerable<T>)set).GetEnumerator();
+        }
+
+        public bool Remove(T item)
+        {
+            return set.Remove(item);
+        }
+
+#if NET_2_0 || SILVERLIGHT
+#if SILVERLIGHT
+        [DataContract]
+#endif
+        private class TDictSet<V> : ICollection<V>
+        {
+#if SILVERLIGHT
+            [DataMember]
+#endif
+            Dictionary<V, TDictSet<V>> dict = new Dictionary<V, TDictSet<V>>();
+
+            public int Count
+            {
+                get { return dict.Count; }
+            }
+
+            public bool IsReadOnly
+            {
+                get { return false; }
+            }
+
+            public IEnumerator GetEnumerator()
+            {
+                return ((IEnumerable)dict.Keys).GetEnumerator();
+            }
+
+            IEnumerator<V> IEnumerable<V>.GetEnumerator()
+            {
+                return dict.Keys.GetEnumerator();
+            }
+
+            public bool Add(V item)
+            {
+                if (!dict.ContainsKey(item))
+                {
+                    dict[item] = this;
+                    return true;
+                }
+
+                return false;
+            }
+
+            void ICollection<V>.Add(V item)
+            {
+                Add(item);
+            }
+
+            public void Clear()
+            {
+                dict.Clear();
+            }
+
+            public bool Contains(V item)
+            {
+                return dict.ContainsKey(item);
+            }
+
+            public void CopyTo(V[] array, int arrayIndex)
+            {
+                dict.Keys.CopyTo(array, arrayIndex);
+            }
+
+            public bool Remove(V item)
+            {
+                return dict.Remove(item);
+            }
+        }
+#endif
+    }
+
+}
diff --git a/lib/csharp/src/Net35/ExtensionsNet35.cs b/lib/csharp/src/Net35/ExtensionsNet35.cs
new file mode 100644
index 0000000..73a4232
--- /dev/null
+++ b/lib/csharp/src/Net35/ExtensionsNet35.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+#if (!NET45)
+namespace Thrift
+{
+    static class StreamExtensionsNet35
+    {
+        // CopyTo() has been added in 4.0
+        public static long CopyTo(this Stream source, Stream target)
+        {
+            byte[] buffer = new byte[8192];  // multiple of 4096
+            long nTotal = 0;
+            while (true)
+            {
+                int nRead = source.Read(buffer, 0, buffer.Length);
+                if (nRead <= 0)  // done?
+                    return nTotal;
+
+                target.Write(buffer, 0, nRead);
+                nTotal += nRead;
+            }
+        }
+    }
+
+}
+#endif
+
diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c8f51b5
--- /dev/null
+++ b/lib/csharp/src/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+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("Thrift")]
+[assembly: AssemblyDescription("C# bindings for the Apache Thrift RPC system")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("The Apache Software Foundation")]
+[assembly: AssemblyProduct("Thrift")]
+[assembly: AssemblyCopyright("The Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+//@TODO where to put License information?
+
+// 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("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")]
+
+// 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("0.14.0.0")]
+[assembly: AssemblyFileVersion("0.14.0.0")]
diff --git a/lib/csharp/src/Protocol/TAbstractBase.cs b/lib/csharp/src/Protocol/TAbstractBase.cs
new file mode 100644
index 0000000..f5a61cd
--- /dev/null
+++ b/lib/csharp/src/Protocol/TAbstractBase.cs
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace Thrift.Protocol
+{
+    public interface TAbstractBase
+    {
+        /// <summary>
+        /// Writes the objects out to the protocol.
+        /// </summary>
+        void Write(TProtocol tProtocol);
+    }
+}
diff --git a/lib/csharp/src/Protocol/TBase.cs b/lib/csharp/src/Protocol/TBase.cs
new file mode 100644
index 0000000..411e4d9
--- /dev/null
+++ b/lib/csharp/src/Protocol/TBase.cs
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace Thrift.Protocol
+{
+    public interface TBase : TAbstractBase
+    {
+        /// <summary>
+        /// Reads the TObject from the given input protocol.
+        /// </summary>
+        void Read(TProtocol tProtocol);
+    }
+}
diff --git a/lib/csharp/src/Protocol/TBase64Utils.cs b/lib/csharp/src/Protocol/TBase64Utils.cs
new file mode 100644
index 0000000..9eaaebd
--- /dev/null
+++ b/lib/csharp/src/Protocol/TBase64Utils.cs
@@ -0,0 +1,100 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+
+namespace Thrift.Protocol
+{
+    internal static class TBase64Utils
+    {
+        internal const string ENCODE_TABLE =
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+        internal static void encode(byte[] src, int srcOff, int len, byte[] dst,
+                                int dstOff)
+        {
+            dst[dstOff] = (byte)ENCODE_TABLE[(src[srcOff] >> 2) & 0x3F];
+            if (len == 3)
+            {
+                dst[dstOff + 1] =
+                    (byte)ENCODE_TABLE[
+                        ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] =
+                    (byte)ENCODE_TABLE[
+                        ((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)];
+                dst[dstOff + 3] =
+                    (byte)ENCODE_TABLE[src[srcOff + 2] & 0x3F];
+            }
+            else if (len == 2)
+            {
+                dst[dstOff + 1] =
+                    (byte)ENCODE_TABLE[
+                        ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] =
+                    (byte)ENCODE_TABLE[(src[srcOff + 1] << 2) & 0x3C];
+
+            }
+            else
+            { // len == 1) {
+                dst[dstOff + 1] =
+                    (byte)ENCODE_TABLE[(src[srcOff] << 4) & 0x30];
+            }
+        }
+
+        private static int[] DECODE_TABLE = {
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
+            52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
+            -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
+            15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
+            -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
+            41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+        };
+
+        internal static void decode(byte[] src, int srcOff, int len, byte[] dst,
+                                 int dstOff)
+        {
+            dst[dstOff] = (byte)
+                ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) |
+                (DECODE_TABLE[src[srcOff + 1] & 0x0FF] >> 4));
+            if (len > 2)
+            {
+                dst[dstOff + 1] = (byte)
+                    (((DECODE_TABLE[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) |
+                    (DECODE_TABLE[src[srcOff + 2] & 0x0FF] >> 2));
+                if (len > 3)
+                {
+                    dst[dstOff + 2] = (byte)
+                        (((DECODE_TABLE[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) |
+                        DECODE_TABLE[src[srcOff + 3] & 0x0FF]);
+                }
+            }
+        }
+
+    }
+}
diff --git a/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs
new file mode 100644
index 0000000..a4faa94
--- /dev/null
+++ b/lib/csharp/src/Protocol/TBinaryProtocol.cs
@@ -0,0 +1,395 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+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;
+
+        #region BinaryProtocol 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((sbyte)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((sbyte)field.Type);
+            WriteI16(field.ID);
+        }
+
+        public override void WriteFieldEnd()
+        {
+        }
+
+        public override void WriteFieldStop()
+        {
+            WriteByte((sbyte)TType.Stop);
+        }
+
+        public override void WriteMapBegin(TMap map)
+        {
+            WriteByte((sbyte)map.KeyType);
+            WriteByte((sbyte)map.ValueType);
+            WriteI32(map.Count);
+        }
+
+        public override void WriteMapEnd()
+        {
+        }
+
+        public override void WriteListBegin(TList list)
+        {
+            WriteByte((sbyte)list.ElementType);
+            WriteI32(list.Count);
+        }
+
+        public override void WriteListEnd()
+        {
+        }
+
+        public override void WriteSetBegin(TSet set)
+        {
+            WriteByte((sbyte)set.ElementType);
+            WriteI32(set.Count);
+        }
+
+        public override void WriteSetEnd()
+        {
+        }
+
+        public override void WriteBool(bool b)
+        {
+            WriteByte(b ? (sbyte)1 : (sbyte)0);
+        }
+
+        private byte[] bout = new byte[1];
+        public override void WriteByte(sbyte b)
+        {
+            bout[0] = (byte)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)
+        {
+#if !SILVERLIGHT
+            WriteI64(BitConverter.DoubleToInt64Bits(d));
+#else
+            var bytes = BitConverter.GetBytes(d);
+            WriteI64(BitConverter.ToInt64(bytes, 0));
+#endif
+        }
+
+        public override void WriteBinary(byte[] b)
+        {
+            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 sbyte ReadByte()
+        {
+            ReadAll(bin, 0, 1);
+            return (sbyte)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)));
+        }
+
+#pragma warning disable 675
+
+        private byte[] i64in = new byte[8];
+        public override long ReadI64()
+        {
+            ReadAll(i64in, 0, 8);
+            unchecked
+            {
+                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)));
+            }
+        }
+
+#pragma warning restore 675
+
+        public override double ReadDouble()
+        {
+#if !SILVERLIGHT
+            return BitConverter.Int64BitsToDouble(ReadI64());
+#else
+            var value = ReadI64();
+            var bytes = BitConverter.GetBytes(value);
+            return BitConverter.ToDouble(bytes, 0);
+#endif
+        }
+
+        public override byte[] ReadBinary()
+        {
+            int size = ReadI32();
+            byte[] buf = new byte[size];
+            trans.ReadAll(buf, 0, size);
+            return buf;
+        }
+        private string ReadStringBody(int size)
+        {
+            byte[] buf = new byte[size];
+            trans.ReadAll(buf, 0, size);
+            return Encoding.UTF8.GetString(buf, 0, buf.Length);
+        }
+
+        private int ReadAll(byte[] buf, int off, int len)
+        {
+            return trans.ReadAll(buf, off, len);
+        }
+
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Protocol/TCompactProtocol.cs b/lib/csharp/src/Protocol/TCompactProtocol.cs
new file mode 100644
index 0000000..ff67397
--- /dev/null
+++ b/lib/csharp/src/Protocol/TCompactProtocol.cs
@@ -0,0 +1,849 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections;
+using System.IO;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol
+{
+    public class TCompactProtocol : TProtocol
+    {
+        private static TStruct ANONYMOUS_STRUCT = new TStruct("");
+        private static TField TSTOP = new TField("", TType.Stop, (short)0);
+
+        private static byte[] ttypeToCompactType = new byte[16];
+
+        private const byte PROTOCOL_ID = 0x82;
+        private const byte VERSION = 1;
+        private const byte VERSION_MASK = 0x1f; // 0001 1111
+        private const byte TYPE_MASK = 0xE0; // 1110 0000
+        private const byte TYPE_BITS = 0x07; // 0000 0111
+        private const int TYPE_SHIFT_AMOUNT = 5;
+
+        /// <summary>
+        /// All of the on-wire type codes.
+        /// </summary>
+        private static class Types
+        {
+            public const byte STOP = 0x00;
+            public const byte BOOLEAN_TRUE = 0x01;
+            public const byte BOOLEAN_FALSE = 0x02;
+            public const byte BYTE = 0x03;
+            public const byte I16 = 0x04;
+            public const byte I32 = 0x05;
+            public const byte I64 = 0x06;
+            public const byte DOUBLE = 0x07;
+            public const byte BINARY = 0x08;
+            public const byte LIST = 0x09;
+            public const byte SET = 0x0A;
+            public const byte MAP = 0x0B;
+            public const byte STRUCT = 0x0C;
+        }
+
+        /// <summary>
+        /// Used to keep track of the last field for the current and previous structs,
+        /// so we can do the delta stuff.
+        /// </summary>
+        private Stack<short> lastField_ = new Stack<short>(15);
+
+        private short lastFieldId_ = 0;
+
+        /// <summary>
+        /// If we encounter a boolean field begin, save the TField here so it can
+        /// have the value incorporated.
+        /// </summary>
+        private Nullable<TField> booleanField_;
+
+        /// <summary>
+        /// If we Read a field header, and it's a boolean field, save the boolean
+        /// value here so that ReadBool can use it.
+        /// </summary>
+        private Nullable<Boolean> boolValue_;
+
+
+        #region CompactProtocol Factory
+
+        public class Factory : TProtocolFactory
+        {
+            public Factory() { }
+
+            public TProtocol GetProtocol(TTransport trans)
+            {
+                return new TCompactProtocol(trans);
+            }
+        }
+
+        #endregion
+
+        public TCompactProtocol(TTransport trans)
+            : base(trans)
+        {
+            ttypeToCompactType[(int)TType.Stop] = Types.STOP;
+            ttypeToCompactType[(int)TType.Bool] = Types.BOOLEAN_TRUE;
+            ttypeToCompactType[(int)TType.Byte] = Types.BYTE;
+            ttypeToCompactType[(int)TType.I16] = Types.I16;
+            ttypeToCompactType[(int)TType.I32] = Types.I32;
+            ttypeToCompactType[(int)TType.I64] = Types.I64;
+            ttypeToCompactType[(int)TType.Double] = Types.DOUBLE;
+            ttypeToCompactType[(int)TType.String] = Types.BINARY;
+            ttypeToCompactType[(int)TType.List] = Types.LIST;
+            ttypeToCompactType[(int)TType.Set] = Types.SET;
+            ttypeToCompactType[(int)TType.Map] = Types.MAP;
+            ttypeToCompactType[(int)TType.Struct] = Types.STRUCT;
+        }
+
+        public void reset()
+        {
+            lastField_.Clear();
+            lastFieldId_ = 0;
+        }
+
+        #region Write Methods
+
+        /// <summary>
+        /// Writes a byte without any possibility of all that field header nonsense.
+        /// Used internally by other writing methods that know they need to Write a byte.
+        /// </summary>
+        private byte[] byteDirectBuffer = new byte[1];
+
+        private void WriteByteDirect(byte b)
+        {
+            byteDirectBuffer[0] = b;
+            trans.Write(byteDirectBuffer);
+        }
+
+        /// <summary>
+        /// Writes a byte without any possibility of all that field header nonsense.
+        /// </summary>
+        private void WriteByteDirect(int n)
+        {
+            WriteByteDirect((byte)n);
+        }
+
+        /// <summary>
+        /// Write an i32 as a varint. Results in 1-5 bytes on the wire.
+        /// TODO: make a permanent buffer like WriteVarint64?
+        /// </summary>
+        byte[] i32buf = new byte[5];
+
+        private void WriteVarint32(uint n)
+        {
+            int idx = 0;
+            while (true)
+            {
+                if ((n & ~0x7F) == 0)
+                {
+                    i32buf[idx++] = (byte)n;
+                    // WriteByteDirect((byte)n);
+                    break;
+                    // return;
+                }
+                else
+                {
+                    i32buf[idx++] = (byte)((n & 0x7F) | 0x80);
+                    // WriteByteDirect((byte)((n & 0x7F) | 0x80));
+                    n >>= 7;
+                }
+            }
+            trans.Write(i32buf, 0, idx);
+        }
+
+        /// <summary>
+        /// Write a message header to the wire. Compact Protocol messages contain the
+        /// protocol version so we can migrate forwards in the future if need be.
+        /// </summary>
+        public override void WriteMessageBegin(TMessage message)
+        {
+            WriteByteDirect(PROTOCOL_ID);
+            WriteByteDirect((byte)((VERSION & VERSION_MASK) | ((((uint)message.Type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK)));
+            WriteVarint32((uint)message.SeqID);
+            WriteString(message.Name);
+        }
+
+        /// <summary>
+        /// Write a struct begin. This doesn't actually put anything on the wire. We
+        /// use it as an opportunity to put special placeholder markers on the field
+        /// stack so we can get the field id deltas correct.
+        /// </summary>
+        public override void WriteStructBegin(TStruct strct)
+        {
+            lastField_.Push(lastFieldId_);
+            lastFieldId_ = 0;
+        }
+
+        /// <summary>
+        /// Write a struct end. This doesn't actually put anything on the wire. We use
+        /// this as an opportunity to pop the last field from the current struct off
+        /// of the field stack.
+        /// </summary>
+        public override void WriteStructEnd()
+        {
+            lastFieldId_ = lastField_.Pop();
+        }
+
+        /// <summary>
+        /// Write a field header containing the field id and field type. If the
+        /// difference between the current field id and the last one is small (&lt; 15),
+        /// then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
+        /// field id will follow the type header as a zigzag varint.
+        /// </summary>
+        public override void WriteFieldBegin(TField field)
+        {
+            if (field.Type == TType.Bool)
+            {
+                // we want to possibly include the value, so we'll wait.
+                booleanField_ = field;
+            }
+            else
+            {
+                WriteFieldBeginInternal(field, 0xFF);
+            }
+        }
+
+        /// <summary>
+        /// The workhorse of WriteFieldBegin. It has the option of doing a
+        /// 'type override' of the type header. This is used specifically in the
+        /// boolean field case.
+        /// </summary>
+        private void WriteFieldBeginInternal(TField field, byte typeOverride)
+        {
+            // short lastField = lastField_.Pop();
+
+            // if there's a type override, use that.
+            byte typeToWrite = typeOverride == 0xFF ? getCompactType(field.Type) : typeOverride;
+
+            // check if we can use delta encoding for the field id
+            if (field.ID > lastFieldId_ && field.ID - lastFieldId_ <= 15)
+            {
+                // Write them together
+                WriteByteDirect((field.ID - lastFieldId_) << 4 | typeToWrite);
+            }
+            else
+            {
+                // Write them separate
+                WriteByteDirect(typeToWrite);
+                WriteI16(field.ID);
+            }
+
+            lastFieldId_ = field.ID;
+            // lastField_.push(field.id);
+        }
+
+        /// <summary>
+        /// Write the STOP symbol so we know there are no more fields in this struct.
+        /// </summary>
+        public override void WriteFieldStop()
+        {
+            WriteByteDirect(Types.STOP);
+        }
+
+        /// <summary>
+        /// Write a map header. If the map is empty, omit the key and value type
+        /// headers, as we don't need any additional information to skip it.
+        /// </summary>
+        public override void WriteMapBegin(TMap map)
+        {
+            if (map.Count == 0)
+            {
+                WriteByteDirect(0);
+            }
+            else
+            {
+                WriteVarint32((uint)map.Count);
+                WriteByteDirect(getCompactType(map.KeyType) << 4 | getCompactType(map.ValueType));
+            }
+        }
+
+        /// <summary>
+        /// Write a list header.
+        /// </summary>
+        public override void WriteListBegin(TList list)
+        {
+            WriteCollectionBegin(list.ElementType, list.Count);
+        }
+
+        /// <summary>
+        /// Write a set header.
+        /// </summary>
+        public override void WriteSetBegin(TSet set)
+        {
+            WriteCollectionBegin(set.ElementType, set.Count);
+        }
+
+        /// <summary>
+        /// Write a boolean value. Potentially, this could be a boolean field, in
+        /// which case the field header info isn't written yet. If so, decide what the
+        /// right type header is for the value and then Write the field header.
+        /// Otherwise, Write a single byte.
+        /// </summary>
+        public override void WriteBool(Boolean b)
+        {
+            if (booleanField_ != null)
+            {
+                // we haven't written the field header yet
+                WriteFieldBeginInternal(booleanField_.Value, b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE);
+                booleanField_ = null;
+            }
+            else
+            {
+                // we're not part of a field, so just Write the value.
+                WriteByteDirect(b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE);
+            }
+        }
+
+        /// <summary>
+        /// Write a byte. Nothing to see here!
+        /// </summary>
+        public override void WriteByte(sbyte b)
+        {
+            WriteByteDirect((byte)b);
+        }
+
+        /// <summary>
+        /// Write an I16 as a zigzag varint.
+        /// </summary>
+        public override void WriteI16(short i16)
+        {
+            WriteVarint32(intToZigZag(i16));
+        }
+
+        /// <summary>
+        /// Write an i32 as a zigzag varint.
+        /// </summary>
+        public override void WriteI32(int i32)
+        {
+            WriteVarint32(intToZigZag(i32));
+        }
+
+        /// <summary>
+        /// Write an i64 as a zigzag varint.
+        /// </summary>
+        public override void WriteI64(long i64)
+        {
+            WriteVarint64(longToZigzag(i64));
+        }
+
+        /// <summary>
+        /// Write a double to the wire as 8 bytes.
+        /// </summary>
+        public override void WriteDouble(double dub)
+        {
+            byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
+            fixedLongToBytes(BitConverter.DoubleToInt64Bits(dub), data, 0);
+            trans.Write(data);
+        }
+
+        /// <summary>
+        /// Write a string to the wire with a varint size preceding.
+        /// </summary>
+        public override void WriteString(string str)
+        {
+            byte[] bytes = UTF8Encoding.UTF8.GetBytes(str);
+            WriteBinary(bytes, 0, bytes.Length);
+        }
+
+        /// <summary>
+        /// Write a byte array, using a varint for the size.
+        /// </summary>
+        public override void WriteBinary(byte[] bin)
+        {
+            WriteBinary(bin, 0, bin.Length);
+        }
+
+        private void WriteBinary(byte[] buf, int offset, int length)
+        {
+            WriteVarint32((uint)length);
+            trans.Write(buf, offset, length);
+        }
+
+        //
+        // These methods are called by structs, but don't actually have any wire
+        // output or purpose.
+        //
+
+        public override void WriteMessageEnd() { }
+        public override void WriteMapEnd() { }
+        public override void WriteListEnd() { }
+        public override void WriteSetEnd() { }
+        public override void WriteFieldEnd() { }
+
+        //
+        // Internal writing methods
+        //
+
+        /// <summary>
+        /// Abstract method for writing the start of lists and sets. List and sets on
+        /// the wire differ only by the type indicator.
+        /// </summary>
+        protected void WriteCollectionBegin(TType elemType, int size)
+        {
+            if (size <= 14)
+            {
+                WriteByteDirect(size << 4 | getCompactType(elemType));
+            }
+            else
+            {
+                WriteByteDirect(0xf0 | getCompactType(elemType));
+                WriteVarint32((uint)size);
+            }
+        }
+
+        /// <summary>
+        /// Write an i64 as a varint. Results in 1-10 bytes on the wire.
+        /// </summary>
+        byte[] varint64out = new byte[10];
+        private void WriteVarint64(ulong n)
+        {
+            int idx = 0;
+            while (true)
+            {
+                if ((n & ~(ulong)0x7FL) == 0)
+                {
+                    varint64out[idx++] = (byte)n;
+                    break;
+                }
+                else
+                {
+                    varint64out[idx++] = ((byte)((n & 0x7F) | 0x80));
+                    n >>= 7;
+                }
+            }
+            trans.Write(varint64out, 0, idx);
+        }
+
+        /// <summary>
+        /// Convert l into a zigzag long. This allows negative numbers to be
+        /// represented compactly as a varint.
+        /// </summary>
+        private ulong longToZigzag(long n)
+        {
+            return (ulong)(n << 1) ^ (ulong)(n >> 63);
+        }
+
+        /// <summary>
+        /// Convert n into a zigzag int. This allows negative numbers to be
+        /// represented compactly as a varint.
+        /// </summary>
+        private uint intToZigZag(int n)
+        {
+            return (uint)(n << 1) ^ (uint)(n >> 31);
+        }
+
+        /// <summary>
+        /// Convert a long into little-endian bytes in buf starting at off and going
+        /// until off+7.
+        /// </summary>
+        private void fixedLongToBytes(long n, byte[] buf, int off)
+        {
+            buf[off + 0] = (byte)(n & 0xff);
+            buf[off + 1] = (byte)((n >> 8) & 0xff);
+            buf[off + 2] = (byte)((n >> 16) & 0xff);
+            buf[off + 3] = (byte)((n >> 24) & 0xff);
+            buf[off + 4] = (byte)((n >> 32) & 0xff);
+            buf[off + 5] = (byte)((n >> 40) & 0xff);
+            buf[off + 6] = (byte)((n >> 48) & 0xff);
+            buf[off + 7] = (byte)((n >> 56) & 0xff);
+        }
+
+        #endregion
+
+        #region ReadMethods
+
+        /// <summary>
+        /// Read a message header.
+        /// </summary>
+        public override TMessage ReadMessageBegin()
+        {
+            byte protocolId = (byte)ReadByte();
+            if (protocolId != PROTOCOL_ID)
+            {
+                throw new TProtocolException("Expected protocol id " + PROTOCOL_ID.ToString("X") + " but got " + protocolId.ToString("X"));
+            }
+            byte versionAndType = (byte)ReadByte();
+            byte version = (byte)(versionAndType & VERSION_MASK);
+            if (version != VERSION)
+            {
+                throw new TProtocolException("Expected version " + VERSION + " but got " + version);
+            }
+            byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
+            int seqid = (int)ReadVarint32();
+            string messageName = ReadString();
+            return new TMessage(messageName, (TMessageType)type, seqid);
+        }
+
+        /// <summary>
+        /// Read a struct begin. There's nothing on the wire for this, but it is our
+        /// opportunity to push a new struct begin marker onto the field stack.
+        /// </summary>
+        public override TStruct ReadStructBegin()
+        {
+            lastField_.Push(lastFieldId_);
+            lastFieldId_ = 0;
+            return ANONYMOUS_STRUCT;
+        }
+
+        /// <summary>
+        /// Doesn't actually consume any wire data, just removes the last field for
+        /// this struct from the field stack.
+        /// </summary>
+        public override void ReadStructEnd()
+        {
+            // consume the last field we Read off the wire.
+            lastFieldId_ = lastField_.Pop();
+        }
+
+        /// <summary>
+        /// Read a field header off the wire.
+        /// </summary>
+        public override TField ReadFieldBegin()
+        {
+            byte type = (byte)ReadByte();
+
+            // if it's a stop, then we can return immediately, as the struct is over.
+            if (type == Types.STOP)
+            {
+                return TSTOP;
+            }
+
+            short fieldId;
+
+            // mask off the 4 MSB of the type header. it could contain a field id delta.
+            short modifier = (short)((type & 0xf0) >> 4);
+            if (modifier == 0)
+            {
+                // not a delta. look ahead for the zigzag varint field id.
+                fieldId = ReadI16();
+            }
+            else
+            {
+                // has a delta. add the delta to the last Read field id.
+                fieldId = (short)(lastFieldId_ + modifier);
+            }
+
+            TField field = new TField("", getTType((byte)(type & 0x0f)), fieldId);
+
+            // if this happens to be a boolean field, the value is encoded in the type
+            if (isBoolType(type))
+            {
+                // save the boolean value in a special instance variable.
+                boolValue_ = (byte)(type & 0x0f) == Types.BOOLEAN_TRUE ? true : false;
+            }
+
+            // push the new field onto the field stack so we can keep the deltas going.
+            lastFieldId_ = field.ID;
+            return field;
+        }
+
+        /// <summary>
+        /// Read a map header off the wire. If the size is zero, skip Reading the key
+        /// and value type. This means that 0-length maps will yield TMaps without the
+        /// "correct" types.
+        /// </summary>
+        public override TMap ReadMapBegin()
+        {
+            int size = (int)ReadVarint32();
+            byte keyAndValueType = size == 0 ? (byte)0 : (byte)ReadByte();
+            return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size);
+        }
+
+        /// <summary>
+        /// Read a list header off the wire. If the list size is 0-14, the size will
+        /// be packed into the element type header. If it's a longer list, the 4 MSB
+        /// of the element type header will be 0xF, and a varint will follow with the
+        /// true size.
+        /// </summary>
+        public override TList ReadListBegin()
+        {
+            byte size_and_type = (byte)ReadByte();
+            int size = (size_and_type >> 4) & 0x0f;
+            if (size == 15)
+            {
+                size = (int)ReadVarint32();
+            }
+            TType type = getTType(size_and_type);
+            return new TList(type, size);
+        }
+
+        /// <summary>
+        /// Read a set header off the wire. If the set size is 0-14, the size will
+        /// be packed into the element type header. If it's a longer set, the 4 MSB
+        /// of the element type header will be 0xF, and a varint will follow with the
+        /// true size.
+        /// </summary>
+        public override TSet ReadSetBegin()
+        {
+            return new TSet(ReadListBegin());
+        }
+
+        /// <summary>
+        /// Read a boolean off the wire. If this is a boolean field, the value should
+        /// already have been Read during ReadFieldBegin, so we'll just consume the
+        /// pre-stored value. Otherwise, Read a byte.
+        /// </summary>
+        public override Boolean ReadBool()
+        {
+            if (boolValue_ != null)
+            {
+                bool result = boolValue_.Value;
+                boolValue_ = null;
+                return result;
+            }
+            return ReadByte() == Types.BOOLEAN_TRUE;
+        }
+
+        byte[] byteRawBuf = new byte[1];
+        /// <summary>
+        /// Read a single byte off the wire. Nothing interesting here.
+        /// </summary>
+        public override sbyte ReadByte()
+        {
+            trans.ReadAll(byteRawBuf, 0, 1);
+            return (sbyte)byteRawBuf[0];
+        }
+
+        /// <summary>
+        /// Read an i16 from the wire as a zigzag varint.
+        /// </summary>
+        public override short ReadI16()
+        {
+            return (short)zigzagToInt(ReadVarint32());
+        }
+
+        /// <summary>
+        /// Read an i32 from the wire as a zigzag varint.
+        /// </summary>
+        public override int ReadI32()
+        {
+            return zigzagToInt(ReadVarint32());
+        }
+
+        /// <summary>
+        /// Read an i64 from the wire as a zigzag varint.
+        /// </summary>
+        public override long ReadI64()
+        {
+            return zigzagToLong(ReadVarint64());
+        }
+
+        /// <summary>
+        /// No magic here - just Read a double off the wire.
+        /// </summary>
+        public override double ReadDouble()
+        {
+            byte[] longBits = new byte[8];
+            trans.ReadAll(longBits, 0, 8);
+            return BitConverter.Int64BitsToDouble(bytesToLong(longBits));
+        }
+
+        /// <summary>
+        /// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
+        /// </summary>
+        public override string ReadString()
+        {
+            int length = (int)ReadVarint32();
+
+            if (length == 0)
+            {
+                return "";
+            }
+
+            return Encoding.UTF8.GetString(ReadBinary(length));
+        }
+
+        /// <summary>
+        /// Read a byte[] from the wire.
+        /// </summary>
+        public override byte[] ReadBinary()
+        {
+            int length = (int)ReadVarint32();
+            if (length == 0) return new byte[0];
+
+            byte[] buf = new byte[length];
+            trans.ReadAll(buf, 0, length);
+            return buf;
+        }
+
+        /// <summary>
+        /// Read a byte[] of a known length from the wire.
+        /// </summary>
+        private byte[] ReadBinary(int length)
+        {
+            if (length == 0) return new byte[0];
+
+            byte[] buf = new byte[length];
+            trans.ReadAll(buf, 0, length);
+            return buf;
+        }
+
+        //
+        // These methods are here for the struct to call, but don't have any wire
+        // encoding.
+        //
+        public override void ReadMessageEnd() { }
+        public override void ReadFieldEnd() { }
+        public override void ReadMapEnd() { }
+        public override void ReadListEnd() { }
+        public override void ReadSetEnd() { }
+
+        //
+        // Internal Reading methods
+        //
+
+        /// <summary>
+        /// Read an i32 from the wire as a varint. The MSB of each byte is set
+        /// if there is another byte to follow. This can Read up to 5 bytes.
+        /// </summary>
+        private uint ReadVarint32()
+        {
+            uint result = 0;
+            int shift = 0;
+            while (true)
+            {
+                byte b = (byte)ReadByte();
+                result |= (uint)(b & 0x7f) << shift;
+                if ((b & 0x80) != 0x80) break;
+                shift += 7;
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Read an i64 from the wire as a proper varint. The MSB of each byte is set
+        /// if there is another byte to follow. This can Read up to 10 bytes.
+        /// </summary>
+        private ulong ReadVarint64()
+        {
+            int shift = 0;
+            ulong result = 0;
+            while (true)
+            {
+                byte b = (byte)ReadByte();
+                result |= (ulong)(b & 0x7f) << shift;
+                if ((b & 0x80) != 0x80) break;
+                shift += 7;
+            }
+
+            return result;
+        }
+
+        #endregion
+
+        //
+        // encoding helpers
+        //
+
+        /// <summary>
+        /// Convert from zigzag int to int.
+        /// </summary>
+        private int zigzagToInt(uint n)
+        {
+            return (int)(n >> 1) ^ (-(int)(n & 1));
+        }
+
+        /// <summary>
+        /// Convert from zigzag long to long.
+        /// </summary>
+        private long zigzagToLong(ulong n)
+        {
+            return (long)(n >> 1) ^ (-(long)(n & 1));
+        }
+
+        /// <summary>
+        /// Note that it's important that the mask bytes are long literals,
+        /// otherwise they'll default to ints, and when you shift an int left 56 bits,
+        /// you just get a messed up int.
+        /// </summary>
+        private long bytesToLong(byte[] bytes)
+        {
+            return
+              ((bytes[7] & 0xffL) << 56) |
+              ((bytes[6] & 0xffL) << 48) |
+              ((bytes[5] & 0xffL) << 40) |
+              ((bytes[4] & 0xffL) << 32) |
+              ((bytes[3] & 0xffL) << 24) |
+              ((bytes[2] & 0xffL) << 16) |
+              ((bytes[1] & 0xffL) << 8) |
+              ((bytes[0] & 0xffL));
+        }
+
+        //
+        // type testing and converting
+        //
+
+        private Boolean isBoolType(byte b)
+        {
+            int lowerNibble = b & 0x0f;
+            return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE;
+        }
+
+        /// <summary>
+        /// Given a TCompactProtocol.Types constant, convert it to its corresponding
+        /// TType value.
+        /// </summary>
+        private TType getTType(byte type)
+        {
+            switch ((byte)(type & 0x0f))
+            {
+                case Types.STOP:
+                    return TType.Stop;
+                case Types.BOOLEAN_FALSE:
+                case Types.BOOLEAN_TRUE:
+                    return TType.Bool;
+                case Types.BYTE:
+                    return TType.Byte;
+                case Types.I16:
+                    return TType.I16;
+                case Types.I32:
+                    return TType.I32;
+                case Types.I64:
+                    return TType.I64;
+                case Types.DOUBLE:
+                    return TType.Double;
+                case Types.BINARY:
+                    return TType.String;
+                case Types.LIST:
+                    return TType.List;
+                case Types.SET:
+                    return TType.Set;
+                case Types.MAP:
+                    return TType.Map;
+                case Types.STRUCT:
+                    return TType.Struct;
+                default:
+                    throw new TProtocolException("don't know what type: " + (byte)(type & 0x0f));
+            }
+        }
+
+        /// <summary>
+        /// Given a TType value, find the appropriate TCompactProtocol.Types constant.
+        /// </summary>
+        private byte getCompactType(TType ttype)
+        {
+            return ttypeToCompactType[(int)ttype];
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TField.cs b/lib/csharp/src/Protocol/TField.cs
new file mode 100644
index 0000000..8179557
--- /dev/null
+++ b/lib/csharp/src/Protocol/TField.cs
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TField
+    {
+        private string name;
+        private TType type;
+        private short id;
+
+        public TField(string name, TType type, short id)
+            :this()
+        {
+            this.name = name;
+            this.type = type;
+            this.id = id;
+        }
+
+        public string Name
+        {
+            get { return name; }
+            set { name = value; }
+        }
+
+        public TType Type
+        {
+            get { return type; }
+            set { type = value; }
+        }
+
+        public short ID
+        {
+            get { return id; }
+            set { id = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TJSONProtocol.cs b/lib/csharp/src/Protocol/TJSONProtocol.cs
new file mode 100644
index 0000000..9dbdea9
--- /dev/null
+++ b/lib/csharp/src/Protocol/TJSONProtocol.cs
@@ -0,0 +1,1124 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+
+using Thrift.Transport;
+using System.Globalization;
+
+namespace Thrift.Protocol
+{
+    /// <summary>
+    /// JSON protocol implementation for thrift.
+    /// <para/>
+    /// This is a full-featured protocol supporting Write and Read.
+    /// <para/>
+    /// Please see the C++ class header for a detailed description of the
+    /// protocol's wire format.
+    /// <para/>
+    /// Adapted from the Java version.
+    /// </summary>
+    public class TJSONProtocol : TProtocol
+    {
+        /// <summary>
+        /// Factory for JSON protocol objects.
+        /// </summary>
+        public class Factory : TProtocolFactory
+        {
+            public TProtocol GetProtocol(TTransport trans)
+            {
+                return new TJSONProtocol(trans);
+            }
+        }
+
+        private static byte[] COMMA = new byte[] { (byte)',' };
+        private static byte[] COLON = new byte[] { (byte)':' };
+        private static byte[] LBRACE = new byte[] { (byte)'{' };
+        private static byte[] RBRACE = new byte[] { (byte)'}' };
+        private static byte[] LBRACKET = new byte[] { (byte)'[' };
+        private static byte[] RBRACKET = new byte[] { (byte)']' };
+        private static byte[] QUOTE = new byte[] { (byte)'"' };
+        private static byte[] BACKSLASH = new byte[] { (byte)'\\' };
+
+        private byte[] ESCSEQ = new byte[] { (byte)'\\', (byte)'u', (byte)'0', (byte)'0' };
+
+        private const long VERSION = 1;
+        private byte[] JSON_CHAR_TABLE = {
+    0,  0,  0,  0,  0,  0,  0,  0,(byte)'b',(byte)'t',(byte)'n',  0,(byte)'f',(byte)'r',  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  1,(byte)'"',  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+  };
+
+        private char[] ESCAPE_CHARS = "\"\\/bfnrt".ToCharArray();
+
+        private byte[] ESCAPE_CHAR_VALS = {
+    (byte)'"', (byte)'\\', (byte)'/', (byte)'\b', (byte)'\f', (byte)'\n', (byte)'\r', (byte)'\t',
+  };
+
+        private const int DEF_STRING_SIZE = 16;
+
+        private static byte[] NAME_BOOL = new byte[] { (byte)'t', (byte)'f' };
+        private static byte[] NAME_BYTE = new byte[] { (byte)'i', (byte)'8' };
+        private static byte[] NAME_I16 = new byte[] { (byte)'i', (byte)'1', (byte)'6' };
+        private static byte[] NAME_I32 = new byte[] { (byte)'i', (byte)'3', (byte)'2' };
+        private static byte[] NAME_I64 = new byte[] { (byte)'i', (byte)'6', (byte)'4' };
+        private static byte[] NAME_DOUBLE = new byte[] { (byte)'d', (byte)'b', (byte)'l' };
+        private static byte[] NAME_STRUCT = new byte[] { (byte)'r', (byte)'e', (byte)'c' };
+        private static byte[] NAME_STRING = new byte[] { (byte)'s', (byte)'t', (byte)'r' };
+        private static byte[] NAME_MAP = new byte[] { (byte)'m', (byte)'a', (byte)'p' };
+        private static byte[] NAME_LIST = new byte[] { (byte)'l', (byte)'s', (byte)'t' };
+        private static byte[] NAME_SET = new byte[] { (byte)'s', (byte)'e', (byte)'t' };
+
+        private static byte[] GetTypeNameForTypeID(TType typeID)
+        {
+            switch (typeID)
+            {
+                case TType.Bool:
+                    return NAME_BOOL;
+                case TType.Byte:
+                    return NAME_BYTE;
+                case TType.I16:
+                    return NAME_I16;
+                case TType.I32:
+                    return NAME_I32;
+                case TType.I64:
+                    return NAME_I64;
+                case TType.Double:
+                    return NAME_DOUBLE;
+                case TType.String:
+                    return NAME_STRING;
+                case TType.Struct:
+                    return NAME_STRUCT;
+                case TType.Map:
+                    return NAME_MAP;
+                case TType.Set:
+                    return NAME_SET;
+                case TType.List:
+                    return NAME_LIST;
+                default:
+                    throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED,
+                                                 "Unrecognized type");
+            }
+        }
+
+        private static TType GetTypeIDForTypeName(byte[] name)
+        {
+            TType result = TType.Stop;
+            if (name.Length > 1)
+            {
+                switch (name[0])
+                {
+                    case (byte)'d':
+                        result = TType.Double;
+                        break;
+                    case (byte)'i':
+                        switch (name[1])
+                        {
+                            case (byte)'8':
+                                result = TType.Byte;
+                                break;
+                            case (byte)'1':
+                                result = TType.I16;
+                                break;
+                            case (byte)'3':
+                                result = TType.I32;
+                                break;
+                            case (byte)'6':
+                                result = TType.I64;
+                                break;
+                        }
+                        break;
+                    case (byte)'l':
+                        result = TType.List;
+                        break;
+                    case (byte)'m':
+                        result = TType.Map;
+                        break;
+                    case (byte)'r':
+                        result = TType.Struct;
+                        break;
+                    case (byte)'s':
+                        if (name[1] == (byte)'t')
+                        {
+                            result = TType.String;
+                        }
+                        else if (name[1] == (byte)'e')
+                        {
+                            result = TType.Set;
+                        }
+                        break;
+                    case (byte)'t':
+                        result = TType.Bool;
+                        break;
+                }
+            }
+            if (result == TType.Stop)
+            {
+                throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED,
+                                             "Unrecognized type");
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Base class for tracking JSON contexts that may require
+        /// inserting/Reading additional JSON syntax characters
+        /// This base context does nothing.
+        /// </summary>
+        protected class JSONBaseContext
+        {
+            protected TJSONProtocol proto;
+
+            public JSONBaseContext(TJSONProtocol proto)
+            {
+                this.proto = proto;
+            }
+
+            public virtual void Write() { }
+
+            public virtual void Read() { }
+
+            public virtual bool EscapeNumbers() { return false; }
+        }
+
+        /// <summary>
+        /// Context for JSON lists. Will insert/Read commas before each item except
+        /// for the first one
+        /// </summary>
+        protected class JSONListContext : JSONBaseContext
+        {
+            public JSONListContext(TJSONProtocol protocol)
+                : base(protocol)
+            {
+
+            }
+
+            private bool first = true;
+
+            public override void Write()
+            {
+                if (first)
+                {
+                    first = false;
+                }
+                else
+                {
+                    proto.trans.Write(COMMA);
+                }
+            }
+
+            public override void Read()
+            {
+                if (first)
+                {
+                    first = false;
+                }
+                else
+                {
+                    proto.ReadJSONSyntaxChar(COMMA);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Context for JSON records. Will insert/Read colons before the value portion
+        /// of each record pair, and commas before each key except the first. In
+        /// addition, will indicate that numbers in the key position need to be
+        /// escaped in quotes (since JSON keys must be strings).
+        /// </summary>
+        protected class JSONPairContext : JSONBaseContext
+        {
+            public JSONPairContext(TJSONProtocol proto)
+                : base(proto)
+            {
+
+            }
+
+            private bool first = true;
+            private bool colon = true;
+
+            public override void Write()
+            {
+                if (first)
+                {
+                    first = false;
+                    colon = true;
+                }
+                else
+                {
+                    proto.trans.Write(colon ? COLON : COMMA);
+                    colon = !colon;
+                }
+            }
+
+            public override void Read()
+            {
+                if (first)
+                {
+                    first = false;
+                    colon = true;
+                }
+                else
+                {
+                    proto.ReadJSONSyntaxChar(colon ? COLON : COMMA);
+                    colon = !colon;
+                }
+            }
+
+            public override bool EscapeNumbers()
+            {
+                return colon;
+            }
+        }
+
+        /// <summary>
+        /// Holds up to one byte from the transport
+        /// </summary>
+        protected class LookaheadReader
+        {
+            protected TJSONProtocol proto;
+
+            public LookaheadReader(TJSONProtocol proto)
+            {
+                this.proto = proto;
+            }
+
+            private bool hasData;
+            private byte[] data = new byte[1];
+
+            /// <summary>
+            /// Return and consume the next byte to be Read, either taking it from the
+            /// data buffer if present or getting it from the transport otherwise.
+            /// </summary>
+            public byte Read()
+            {
+                if (hasData)
+                {
+                    hasData = false;
+                }
+                else
+                {
+                    proto.trans.ReadAll(data, 0, 1);
+                }
+                return data[0];
+            }
+
+            /// <summary>
+            /// Return the next byte to be Read without consuming, filling the data
+            /// buffer if it has not been filled alReady.
+            /// </summary>
+            public byte Peek()
+            {
+                if (!hasData)
+                {
+                    proto.trans.ReadAll(data, 0, 1);
+                }
+                hasData = true;
+                return data[0];
+            }
+        }
+
+        // Default encoding
+        protected Encoding utf8Encoding = UTF8Encoding.UTF8;
+
+        // Stack of nested contexts that we may be in
+        protected Stack<JSONBaseContext> contextStack = new Stack<JSONBaseContext>();
+
+        // Current context that we are in
+        protected JSONBaseContext context;
+
+        // Reader that manages a 1-byte buffer
+        protected LookaheadReader reader;
+
+        /// <summary>
+        /// Push a new JSON context onto the stack.
+        /// </summary>
+        protected void PushContext(JSONBaseContext c)
+        {
+            contextStack.Push(context);
+            context = c;
+        }
+
+        /// <summary>
+        /// Pop the last JSON context off the stack
+        /// </summary>
+        protected void PopContext()
+        {
+            context = contextStack.Pop();
+        }
+
+        /// <summary>
+        /// TJSONProtocol Constructor
+        /// </summary>
+        public TJSONProtocol(TTransport trans)
+            : base(trans)
+        {
+            context = new JSONBaseContext(this);
+            reader = new LookaheadReader(this);
+        }
+
+        // Temporary buffer used by several methods
+        private byte[] tempBuffer = new byte[4];
+
+        /// <summary>
+        /// Read a byte that must match b[0]; otherwise an exception is thrown.
+        /// Marked protected to avoid synthetic accessor in JSONListContext.Read
+        /// and JSONPairContext.Read
+        /// </summary>
+        protected void ReadJSONSyntaxChar(byte[] b)
+        {
+            byte ch = reader.Read();
+            if (ch != b[0])
+            {
+                throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                             "Unexpected character:" + (char)ch);
+            }
+        }
+
+        /// <summary>
+        /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
+        /// corresponding hex value
+        /// </summary>
+        private static byte HexVal(byte ch)
+        {
+            if ((ch >= '0') && (ch <= '9'))
+            {
+                return (byte)((char)ch - '0');
+            }
+            else if ((ch >= 'a') && (ch <= 'f'))
+            {
+                ch += 10;
+                return (byte)((char)ch - 'a');
+            }
+            else
+            {
+                throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                             "Expected hex character");
+            }
+        }
+
+        /// <summary>
+        /// Convert a byte containing a hex value to its corresponding hex character
+        /// </summary>
+        private static byte HexChar(byte val)
+        {
+            val &= 0x0F;
+            if (val < 10)
+            {
+                return (byte)((char)val + '0');
+            }
+            else
+            {
+                val -= 10;
+                return (byte)((char)val + 'a');
+            }
+        }
+
+        /// <summary>
+        /// Write the bytes in array buf as a JSON characters, escaping as needed
+        /// </summary>
+        private void WriteJSONString(byte[] b)
+        {
+            context.Write();
+            trans.Write(QUOTE);
+            int len = b.Length;
+            for (int i = 0; i < len; i++)
+            {
+                if ((b[i] & 0x00FF) >= 0x30)
+                {
+                    if (b[i] == BACKSLASH[0])
+                    {
+                        trans.Write(BACKSLASH);
+                        trans.Write(BACKSLASH);
+                    }
+                    else
+                    {
+                        trans.Write(b, i, 1);
+                    }
+                }
+                else
+                {
+                    tempBuffer[0] = JSON_CHAR_TABLE[b[i]];
+                    if (tempBuffer[0] == 1)
+                    {
+                        trans.Write(b, i, 1);
+                    }
+                    else if (tempBuffer[0] > 1)
+                    {
+                        trans.Write(BACKSLASH);
+                        trans.Write(tempBuffer, 0, 1);
+                    }
+                    else
+                    {
+                        trans.Write(ESCSEQ);
+                        tempBuffer[0] = HexChar((byte)(b[i] >> 4));
+                        tempBuffer[1] = HexChar(b[i]);
+                        trans.Write(tempBuffer, 0, 2);
+                    }
+                }
+            }
+            trans.Write(QUOTE);
+        }
+
+        /// <summary>
+        /// Write out number as a JSON value. If the context dictates so, it will be
+        /// wrapped in quotes to output as a JSON string.
+        /// </summary>
+        private void WriteJSONInteger(long num)
+        {
+            context.Write();
+            string str = num.ToString();
+
+            bool escapeNum = context.EscapeNumbers();
+            if (escapeNum)
+                trans.Write(QUOTE);
+
+            trans.Write(utf8Encoding.GetBytes(str));
+
+            if (escapeNum)
+                trans.Write(QUOTE);
+        }
+
+        /// <summary>
+        /// Write out a double as a JSON value. If it is NaN or infinity or if the
+        /// context dictates escaping, Write out as JSON string.
+        /// </summary>
+        private void WriteJSONDouble(double num)
+        {
+            context.Write();
+            string str = num.ToString("G17", CultureInfo.InvariantCulture);
+            bool special = false;
+
+            switch (str[0])
+            {
+                case 'N': // NaN
+                case 'I': // Infinity
+                    special = true;
+                    break;
+                case '-':
+                    if (str[1] == 'I')
+                    { // -Infinity
+                        special = true;
+                    }
+                    break;
+            }
+
+            bool escapeNum = special || context.EscapeNumbers();
+
+            if (escapeNum)
+                trans.Write(QUOTE);
+
+            trans.Write(utf8Encoding.GetBytes(str));
+
+            if (escapeNum)
+                trans.Write(QUOTE);
+        }
+        /// <summary>
+        /// Write out contents of byte array b as a JSON string with base-64 encoded
+        /// data
+        /// </summary>
+        private void WriteJSONBase64(byte[] b)
+        {
+            context.Write();
+            trans.Write(QUOTE);
+
+            int len = b.Length;
+            int off = 0;
+
+            while (len >= 3)
+            {
+                // Encode 3 bytes at a time
+                TBase64Utils.encode(b, off, 3, tempBuffer, 0);
+                trans.Write(tempBuffer, 0, 4);
+                off += 3;
+                len -= 3;
+            }
+            if (len > 0)
+            {
+                // Encode remainder
+                TBase64Utils.encode(b, off, len, tempBuffer, 0);
+                trans.Write(tempBuffer, 0, len + 1);
+            }
+
+            trans.Write(QUOTE);
+        }
+
+        private void WriteJSONObjectStart()
+        {
+            context.Write();
+            trans.Write(LBRACE);
+            PushContext(new JSONPairContext(this));
+        }
+
+        private void WriteJSONObjectEnd()
+        {
+            PopContext();
+            trans.Write(RBRACE);
+        }
+
+        private void WriteJSONArrayStart()
+        {
+            context.Write();
+            trans.Write(LBRACKET);
+            PushContext(new JSONListContext(this));
+        }
+
+        private void WriteJSONArrayEnd()
+        {
+            PopContext();
+            trans.Write(RBRACKET);
+        }
+
+        public override void WriteMessageBegin(TMessage message)
+        {
+            WriteJSONArrayStart();
+            WriteJSONInteger(VERSION);
+
+            byte[] b = utf8Encoding.GetBytes(message.Name);
+            WriteJSONString(b);
+
+            WriteJSONInteger((long)message.Type);
+            WriteJSONInteger(message.SeqID);
+        }
+
+        public override void WriteMessageEnd()
+        {
+            WriteJSONArrayEnd();
+        }
+
+        public override void WriteStructBegin(TStruct str)
+        {
+            WriteJSONObjectStart();
+        }
+
+        public override void WriteStructEnd()
+        {
+            WriteJSONObjectEnd();
+        }
+
+        public override void WriteFieldBegin(TField field)
+        {
+            WriteJSONInteger(field.ID);
+            WriteJSONObjectStart();
+            WriteJSONString(GetTypeNameForTypeID(field.Type));
+        }
+
+        public override void WriteFieldEnd()
+        {
+            WriteJSONObjectEnd();
+        }
+
+        public override void WriteFieldStop() { }
+
+        public override void WriteMapBegin(TMap map)
+        {
+            WriteJSONArrayStart();
+            WriteJSONString(GetTypeNameForTypeID(map.KeyType));
+            WriteJSONString(GetTypeNameForTypeID(map.ValueType));
+            WriteJSONInteger(map.Count);
+            WriteJSONObjectStart();
+        }
+
+        public override void WriteMapEnd()
+        {
+            WriteJSONObjectEnd();
+            WriteJSONArrayEnd();
+        }
+
+        public override void WriteListBegin(TList list)
+        {
+            WriteJSONArrayStart();
+            WriteJSONString(GetTypeNameForTypeID(list.ElementType));
+            WriteJSONInteger(list.Count);
+        }
+
+        public override void WriteListEnd()
+        {
+            WriteJSONArrayEnd();
+        }
+
+        public override void WriteSetBegin(TSet set)
+        {
+            WriteJSONArrayStart();
+            WriteJSONString(GetTypeNameForTypeID(set.ElementType));
+            WriteJSONInteger(set.Count);
+        }
+
+        public override void WriteSetEnd()
+        {
+            WriteJSONArrayEnd();
+        }
+
+        public override void WriteBool(bool b)
+        {
+            WriteJSONInteger(b ? (long)1 : (long)0);
+        }
+
+        public override void WriteByte(sbyte b)
+        {
+            WriteJSONInteger((long)b);
+        }
+
+        public override void WriteI16(short i16)
+        {
+            WriteJSONInteger((long)i16);
+        }
+
+        public override void WriteI32(int i32)
+        {
+            WriteJSONInteger((long)i32);
+        }
+
+        public override void WriteI64(long i64)
+        {
+            WriteJSONInteger(i64);
+        }
+
+        public override void WriteDouble(double dub)
+        {
+            WriteJSONDouble(dub);
+        }
+
+        public override void WriteString(string str)
+        {
+            byte[] b = utf8Encoding.GetBytes(str);
+            WriteJSONString(b);
+        }
+
+        public override void WriteBinary(byte[] bin)
+        {
+            WriteJSONBase64(bin);
+        }
+
+        /**
+         * Reading methods.
+         */
+
+        /// <summary>
+        /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the
+        /// context if skipContext is true.
+        /// </summary>
+        private byte[] ReadJSONString(bool skipContext)
+        {
+            MemoryStream buffer = new MemoryStream();
+            List<char> codeunits = new List<char>();
+
+
+            if (!skipContext)
+            {
+                context.Read();
+            }
+            ReadJSONSyntaxChar(QUOTE);
+            while (true)
+            {
+                byte ch = reader.Read();
+                if (ch == QUOTE[0])
+                {
+                    break;
+                }
+
+                // escaped?
+                if (ch != ESCSEQ[0])
+                {
+                    buffer.Write(new byte[] { (byte)ch }, 0, 1);
+                    continue;
+                }
+
+                // distinguish between \uXXXX and \?
+                ch = reader.Read();
+                if (ch != ESCSEQ[1])  // control chars like \n
+                {
+                    int off = Array.IndexOf(ESCAPE_CHARS, (char)ch);
+                    if (off == -1)
+                    {
+                        throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                        "Expected control char");
+                    }
+                    ch = ESCAPE_CHAR_VALS[off];
+                    buffer.Write(new byte[] { (byte)ch }, 0, 1);
+                    continue;
+                }
+
+
+                // it's \uXXXX
+                trans.ReadAll(tempBuffer, 0, 4);
+                var wch = (short)((HexVal((byte)tempBuffer[0]) << 12) +
+                                  (HexVal((byte)tempBuffer[1]) << 8) +
+                                  (HexVal((byte)tempBuffer[2]) << 4) +
+                                   HexVal(tempBuffer[3]));
+                if (Char.IsHighSurrogate((char)wch))
+                {
+                    if (codeunits.Count > 0)
+                    {
+                        throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                        "Expected low surrogate char");
+                    }
+                    codeunits.Add((char)wch);
+                }
+                else if (Char.IsLowSurrogate((char)wch))
+                {
+                    if (codeunits.Count == 0)
+                    {
+                        throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                        "Expected high surrogate char");
+                    }
+                    codeunits.Add((char)wch);
+                    var tmp = utf8Encoding.GetBytes(codeunits.ToArray());
+                    buffer.Write(tmp, 0, tmp.Length);
+                    codeunits.Clear();
+                }
+                else
+                {
+                    var tmp = utf8Encoding.GetBytes(new char[] { (char)wch });
+                    buffer.Write(tmp, 0, tmp.Length);
+                }
+            }
+
+
+            if (codeunits.Count > 0)
+            {
+                throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                "Expected low surrogate char");
+            }
+
+            return buffer.ToArray();
+        }
+
+        /// <summary>
+        /// Return true if the given byte could be a valid part of a JSON number.
+        /// </summary>
+        private bool IsJSONNumeric(byte b)
+        {
+            switch (b)
+            {
+                case (byte)'+':
+                case (byte)'-':
+                case (byte)'.':
+                case (byte)'0':
+                case (byte)'1':
+                case (byte)'2':
+                case (byte)'3':
+                case (byte)'4':
+                case (byte)'5':
+                case (byte)'6':
+                case (byte)'7':
+                case (byte)'8':
+                case (byte)'9':
+                case (byte)'E':
+                case (byte)'e':
+                    return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Read in a sequence of characters that are all valid in JSON numbers. Does
+        /// not do a complete regex check to validate that this is actually a number.
+        /// </summary>
+        private string ReadJSONNumericChars()
+        {
+            StringBuilder strbld = new StringBuilder();
+            while (true)
+            {
+                byte ch = reader.Peek();
+                if (!IsJSONNumeric(ch))
+                {
+                    break;
+                }
+                strbld.Append((char)reader.Read());
+            }
+            return strbld.ToString();
+        }
+
+        /// <summary>
+        /// Read in a JSON number. If the context dictates, Read in enclosing quotes.
+        /// </summary>
+        private long ReadJSONInteger()
+        {
+            context.Read();
+            if (context.EscapeNumbers())
+            {
+                ReadJSONSyntaxChar(QUOTE);
+            }
+
+            string str = ReadJSONNumericChars();
+            if (context.EscapeNumbers())
+            {
+                ReadJSONSyntaxChar(QUOTE);
+            }
+
+            try
+            {
+                return Int64.Parse(str);
+            }
+            catch (FormatException fex)
+            {
+                throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                             "Bad data encounted in numeric data", fex);
+            }
+        }
+
+        /// <summary>
+        /// Read in a JSON double value. Throw if the value is not wrapped in quotes
+        /// when expected or if wrapped in quotes when not expected.
+        /// </summary>
+        private double ReadJSONDouble()
+        {
+            context.Read();
+            if (reader.Peek() == QUOTE[0])
+            {
+                byte[] arr = ReadJSONString(true);
+                double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
+
+                if (!context.EscapeNumbers() && !Double.IsNaN(dub) && !Double.IsInfinity(dub))
+                {
+                    // Throw exception -- we should not be in a string in this case
+                    throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                 "Numeric data unexpectedly quoted");
+                }
+                return dub;
+            }
+            else
+            {
+                if (context.EscapeNumbers())
+                {
+                    // This will throw - we should have had a quote if escapeNum == true
+                    ReadJSONSyntaxChar(QUOTE);
+                }
+                try
+                {
+                    return Double.Parse(ReadJSONNumericChars(), CultureInfo.InvariantCulture);
+                }
+                catch (FormatException fex)
+                {
+                    throw new TProtocolException(TProtocolException.INVALID_DATA,
+                                                 "Bad data encounted in numeric data", fex);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Read in a JSON string containing base-64 encoded data and decode it.
+        /// </summary>
+        private byte[] ReadJSONBase64()
+        {
+            byte[] b = ReadJSONString(false);
+            int len = b.Length;
+            int off = 0;
+            int size = 0;
+            // reduce len to ignore fill bytes
+            while ((len > 0) && (b[len - 1] == '='))
+            {
+                --len;
+            }
+            // read & decode full byte triplets = 4 source bytes
+            while (len > 4)
+            {
+                // Decode 4 bytes at a time
+                TBase64Utils.decode(b, off, 4, b, size); // NB: decoded in place
+                off += 4;
+                len -= 4;
+                size += 3;
+            }
+            // Don't decode if we hit the end or got a single leftover byte (invalid
+            // base64 but legal for skip of regular string type)
+            if (len > 1)
+            {
+                // Decode remainder
+                TBase64Utils.decode(b, off, len, b, size); // NB: decoded in place
+                size += len - 1;
+            }
+            // Sadly we must copy the byte[] (any way around this?)
+            byte[] result = new byte[size];
+            Array.Copy(b, 0, result, 0, size);
+            return result;
+        }
+
+        private void ReadJSONObjectStart()
+        {
+            context.Read();
+            ReadJSONSyntaxChar(LBRACE);
+            PushContext(new JSONPairContext(this));
+        }
+
+        private void ReadJSONObjectEnd()
+        {
+            ReadJSONSyntaxChar(RBRACE);
+            PopContext();
+        }
+
+        private void ReadJSONArrayStart()
+        {
+            context.Read();
+            ReadJSONSyntaxChar(LBRACKET);
+            PushContext(new JSONListContext(this));
+        }
+
+        private void ReadJSONArrayEnd()
+        {
+            ReadJSONSyntaxChar(RBRACKET);
+            PopContext();
+        }
+
+        public override TMessage ReadMessageBegin()
+        {
+            TMessage message = new TMessage();
+            ReadJSONArrayStart();
+            if (ReadJSONInteger() != VERSION)
+            {
+                throw new TProtocolException(TProtocolException.BAD_VERSION,
+                                             "Message contained bad version.");
+            }
+
+            var buf = ReadJSONString(false);
+            message.Name = utf8Encoding.GetString(buf, 0, buf.Length);
+            message.Type = (TMessageType)ReadJSONInteger();
+            message.SeqID = (int)ReadJSONInteger();
+            return message;
+        }
+
+        public override void ReadMessageEnd()
+        {
+            ReadJSONArrayEnd();
+        }
+
+        public override TStruct ReadStructBegin()
+        {
+            ReadJSONObjectStart();
+            return new TStruct();
+        }
+
+        public override void ReadStructEnd()
+        {
+            ReadJSONObjectEnd();
+        }
+
+        public override TField ReadFieldBegin()
+        {
+            TField field = new TField();
+            byte ch = reader.Peek();
+            if (ch == RBRACE[0])
+            {
+                field.Type = TType.Stop;
+            }
+            else
+            {
+                field.ID = (short)ReadJSONInteger();
+                ReadJSONObjectStart();
+                field.Type = GetTypeIDForTypeName(ReadJSONString(false));
+            }
+            return field;
+        }
+
+        public override void ReadFieldEnd()
+        {
+            ReadJSONObjectEnd();
+        }
+
+        public override TMap ReadMapBegin()
+        {
+            TMap map = new TMap();
+            ReadJSONArrayStart();
+            map.KeyType = GetTypeIDForTypeName(ReadJSONString(false));
+            map.ValueType = GetTypeIDForTypeName(ReadJSONString(false));
+            map.Count = (int)ReadJSONInteger();
+            ReadJSONObjectStart();
+            return map;
+        }
+
+        public override void ReadMapEnd()
+        {
+            ReadJSONObjectEnd();
+            ReadJSONArrayEnd();
+        }
+
+        public override TList ReadListBegin()
+        {
+            TList list = new TList();
+            ReadJSONArrayStart();
+            list.ElementType = GetTypeIDForTypeName(ReadJSONString(false));
+            list.Count = (int)ReadJSONInteger();
+            return list;
+        }
+
+        public override void ReadListEnd()
+        {
+            ReadJSONArrayEnd();
+        }
+
+        public override TSet ReadSetBegin()
+        {
+            TSet set = new TSet();
+            ReadJSONArrayStart();
+            set.ElementType = GetTypeIDForTypeName(ReadJSONString(false));
+            set.Count = (int)ReadJSONInteger();
+            return set;
+        }
+
+        public override void ReadSetEnd()
+        {
+            ReadJSONArrayEnd();
+        }
+
+        public override bool ReadBool()
+        {
+            return (ReadJSONInteger() == 0 ? false : true);
+        }
+
+        public override sbyte ReadByte()
+        {
+            return (sbyte)ReadJSONInteger();
+        }
+
+        public override short ReadI16()
+        {
+            return (short)ReadJSONInteger();
+        }
+
+        public override int ReadI32()
+        {
+            return (int)ReadJSONInteger();
+        }
+
+        public override long ReadI64()
+        {
+            return (long)ReadJSONInteger();
+        }
+
+        public override double ReadDouble()
+        {
+            return ReadJSONDouble();
+        }
+
+        public override string ReadString()
+        {
+            var buf = ReadJSONString(false);
+            return utf8Encoding.GetString(buf, 0, buf.Length);
+        }
+
+        public override byte[] ReadBinary()
+        {
+            return ReadJSONBase64();
+        }
+
+    }
+}
diff --git a/lib/csharp/src/Protocol/TList.cs b/lib/csharp/src/Protocol/TList.cs
new file mode 100644
index 0000000..0c8f214
--- /dev/null
+++ b/lib/csharp/src/Protocol/TList.cs
@@ -0,0 +1,54 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TList
+    {
+        private TType elementType;
+        private int count;
+
+        public TList(TType elementType, int count)
+            :this()
+        {
+            this.elementType = elementType;
+            this.count = count;
+        }
+
+        public TType ElementType
+        {
+            get { return elementType; }
+            set { elementType = value; }
+        }
+
+        public int Count
+        {
+            get { return count; }
+            set { count = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TMap.cs b/lib/csharp/src/Protocol/TMap.cs
new file mode 100644
index 0000000..aba9d3a
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMap.cs
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TMap
+    {
+        private TType keyType;
+        private TType valueType;
+        private int count;
+
+        public TMap(TType keyType, TType valueType, int count)
+            :this()
+        {
+            this.keyType = keyType;
+            this.valueType = valueType;
+            this.count = count;
+        }
+
+        public TType KeyType
+        {
+            get { return keyType; }
+            set { keyType = value; }
+        }
+
+        public TType ValueType
+        {
+            get { return valueType; }
+            set { valueType = value; }
+        }
+
+        public int Count
+        {
+            get { return count; }
+            set { count = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TMessage.cs b/lib/csharp/src/Protocol/TMessage.cs
new file mode 100644
index 0000000..348263c
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMessage.cs
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TMessage
+    {
+        private string name;
+        private TMessageType type;
+        private int seqID;
+
+        public TMessage(string name, TMessageType type, int seqid)
+            :this()
+        {
+            this.name = name;
+            this.type = type;
+            this.seqID = seqid;
+        }
+
+        public string Name
+        {
+            get { return name; }
+            set { name = value; }
+        }
+
+        public TMessageType Type
+        {
+            get { return type; }
+            set { type = value; }
+        }
+
+        public int SeqID
+        {
+            get { return seqID; }
+            set { seqID = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TMessageType.cs b/lib/csharp/src/Protocol/TMessageType.cs
new file mode 100644
index 0000000..c7091fe
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMessageType.cs
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+
+namespace Thrift.Protocol
+{
+    public enum TMessageType
+    {
+        Call = 1,
+        Reply = 2,
+        Exception = 3,
+        Oneway = 4
+    }
+}
diff --git a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
new file mode 100644
index 0000000..aa91c52
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs
@@ -0,0 +1,183 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Thrift.Protocol
+{
+    /// <summary>
+    /// <see cref="TMultiplexedProcessor"/> is a <see cref="TProcessor"/> allowing a single <see cref="Thrift.Server.TServer"/>
+    /// to provide multiple services.
+    /// <para/>
+    /// To do so, you instantiate the processor and then register additional processors with it,
+    /// as shown in the following example:
+    /// <para/>
+    /// <code>
+    ///     TMultiplexedProcessor processor = new TMultiplexedProcessor();
+    ///
+    ///     processor.registerProcessor(
+    ///         "Calculator",
+    ///         new Calculator.Processor(new CalculatorHandler()));
+    ///
+    ///     processor.registerProcessor(
+    ///         "WeatherReport",
+    ///         new WeatherReport.Processor(new WeatherReportHandler()));
+    ///
+    ///     TServerTransport t = new TServerSocket(9090);
+    ///     TSimpleServer server = new TSimpleServer(processor, t);
+    ///
+    ///     server.serve();
+    /// </code>
+    /// </summary>
+    public class TMultiplexedProcessor : TProcessor
+    {
+        private Dictionary<string, TProcessor> ServiceProcessorMap = new Dictionary<string, TProcessor>();
+
+        /// <summary>
+        /// 'Register' a service with this TMultiplexedProcessor. This allows us to broker
+        /// requests to individual services by using the service name to select them at request time.
+        ///
+        /// Args:
+        /// - serviceName    Name of a service, has to be identical to the name
+        ///                  declared in the Thrift IDL, e.g. "WeatherReport".
+        /// - processor      Implementation of a service, usually referred to as "handlers",
+        ///                  e.g. WeatherReportHandler implementing WeatherReport.Iface.
+        /// </summary>
+        public void RegisterProcessor(string serviceName, TProcessor processor)
+        {
+            ServiceProcessorMap.Add(serviceName, processor);
+        }
+
+
+        private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
+        {
+            TApplicationException appex = new TApplicationException(extype, etxt);
+
+            TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID);
+
+            oprot.WriteMessageBegin(newMessage);
+            appex.Write(oprot);
+            oprot.WriteMessageEnd();
+            oprot.Transport.Flush();
+        }
+
+
+        /// <summary>
+        /// This implementation of process performs the following steps:
+        ///
+        /// - Read the beginning of the message.
+        /// - Extract the service name from the message.
+        /// - Using the service name to locate the appropriate processor.
+        /// - Dispatch to the processor, with a decorated instance of TProtocol
+        ///    that allows readMessageBegin() to return the original TMessage.
+        /// <para/>
+        /// Throws an exception if
+        /// - the message type is not CALL or ONEWAY,
+        /// - the service name was not found in the message, or
+        /// - the service name has not been RegisterProcessor()ed.
+        /// </summary>
+        public bool Process(TProtocol iprot, TProtocol oprot)
+        {
+            /*  Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
+                message header.  This pulls the message "off the wire", which we'll
+                deal with at the end of this method. */
+
+            try
+            {
+                TMessage message = iprot.ReadMessageBegin();
+
+                if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway))
+                {
+                    Fail(oprot, message,
+                          TApplicationException.ExceptionType.InvalidMessageType,
+                          "Message type CALL or ONEWAY expected");
+                    return false;
+                }
+
+                // Extract the service name
+                int index = message.Name.IndexOf(TMultiplexedProtocol.SEPARATOR);
+                if (index < 0)
+                {
+                    Fail(oprot, message,
+                          TApplicationException.ExceptionType.InvalidProtocol,
+                          "Service name not found in message name: " + message.Name + ". " +
+                          "Did you forget to use a TMultiplexProtocol in your client?");
+                    return false;
+                }
+
+                // Create a new TMessage, something that can be consumed by any TProtocol
+                string serviceName = message.Name.Substring(0, index);
+                TProcessor actualProcessor;
+                if (!ServiceProcessorMap.TryGetValue(serviceName, out actualProcessor))
+                {
+                    Fail(oprot, message,
+                          TApplicationException.ExceptionType.InternalError,
+                          "Service name not found: " + serviceName + ". " +
+                          "Did you forget to call RegisterProcessor()?");
+                    return false;
+                }
+
+                // Create a new TMessage, removing the service name
+                TMessage newMessage = new TMessage(
+                        message.Name.Substring(serviceName.Length + TMultiplexedProtocol.SEPARATOR.Length),
+                        message.Type,
+                        message.SeqID);
+
+                // Dispatch processing to the stored processor
+                return actualProcessor.Process(new StoredMessageProtocol(iprot, newMessage), oprot);
+
+            }
+            catch (IOException)
+            {
+                return false;  // similar to all other processors
+            }
+
+        }
+
+        /// <summary>
+        ///  Our goal was to work with any protocol.  In order to do that, we needed
+        ///  to allow them to call readMessageBegin() and get a TMessage in exactly
+        ///  the standard format, without the service name prepended to TMessage.name.
+        /// </summary>
+        private class StoredMessageProtocol : TProtocolDecorator
+        {
+            TMessage MsgBegin;
+
+            public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin)
+                : base(protocol)
+            {
+                this.MsgBegin = messageBegin;
+            }
+
+            public override TMessage ReadMessageBegin()
+            {
+                return MsgBegin;
+            }
+        }
+
+    }
+}
diff --git a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
new file mode 100644
index 0000000..1bd420f
--- /dev/null
+++ b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs
@@ -0,0 +1,103 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol
+{
+
+    /// <summary>
+    /// TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
+    /// client to communicate with a multiplexing Thrift server, by prepending the service name
+    /// to the function name during function calls.
+    /// <para/>
+    /// NOTE: THIS IS NOT TO BE USED BY SERVERS.
+    /// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
+    /// <para/>
+    /// This example uses a single socket transport to invoke two services:
+    /// <code>
+    ///     TSocket transport = new TSocket("localhost", 9090);
+    ///     transport.open();
+    ///
+    ///     TBinaryProtocol protocol = new TBinaryProtocol(transport);
+    ///
+    ///     TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
+    ///     Calculator.Client service = new Calculator.Client(mp);
+    ///
+    ///     TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
+    ///     WeatherReport.Client service2 = new WeatherReport.Client(mp2);
+    ///
+    ///     System.out.println(service.add(2,2));
+    ///     System.out.println(service2.getTemperature());
+    /// </code>
+    /// </summary>
+    public class TMultiplexedProtocol : TProtocolDecorator
+    {
+
+        /// <summary>
+        /// Used to delimit the service name from the function name.
+        /// </summary>
+        public static string SEPARATOR = ":";
+
+        private string ServiceName;
+
+        /// <summary>
+        /// Wrap the specified protocol, allowing it to be used to communicate with a
+        /// multiplexing server.  The <paramref name="serviceName"/> is required as it is
+        /// prepended to the message header so that the multiplexing server can broker
+        /// the function call to the proper service.
+        /// </summary>
+        /// <param name="protocol">Your communication protocol of choice, e.g. <see cref="TBinaryProtocol"/>.</param>
+        /// <param name="serviceName">The service name of the service communicating via this protocol.</param>
+        public TMultiplexedProtocol(TProtocol protocol, string serviceName)
+            : base(protocol)
+        {
+            ServiceName = serviceName;
+        }
+
+        /// <summary>
+        /// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
+        /// </summary>
+        /// <param name="tMessage">The original message.</param>
+        public override void WriteMessageBegin(TMessage tMessage)
+        {
+            switch (tMessage.Type)
+            {
+                case TMessageType.Call:
+                case TMessageType.Oneway:
+                    base.WriteMessageBegin(new TMessage(
+                        ServiceName + SEPARATOR + tMessage.Name,
+                        tMessage.Type,
+                        tMessage.SeqID));
+                    break;
+
+                default:
+                    base.WriteMessageBegin(tMessage);
+                    break;
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TProtocol.cs b/lib/csharp/src/Protocol/TProtocol.cs
new file mode 100644
index 0000000..dd7a6e0
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocol.cs
@@ -0,0 +1,142 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+
+namespace Thrift.Protocol
+{
+    public abstract class TProtocol : IDisposable
+    {
+        private const int DEFAULT_RECURSION_DEPTH = 64;
+
+        protected TTransport trans;
+        protected int recursionLimit;
+        protected int recursionDepth;
+
+        protected TProtocol(TTransport trans)
+        {
+            this.trans = trans;
+            this.recursionLimit = DEFAULT_RECURSION_DEPTH;
+            this.recursionDepth = 0;
+        }
+
+        public TTransport Transport
+        {
+            get { return trans; }
+        }
+
+        public int RecursionLimit
+        {
+            get { return recursionLimit; }
+            set { recursionLimit = value; }
+        }
+
+        public void IncrementRecursionDepth()
+        {
+            if (recursionDepth < recursionLimit)
+                ++recursionDepth;
+            else
+                throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded");
+        }
+
+        public void DecrementRecursionDepth()
+        {
+            --recursionDepth;
+        }
+
+        #region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        public void Dispose()
+        {
+            Dispose(true);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (trans is IDisposable)
+                        (trans as IDisposable).Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+
+        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(sbyte 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 virtual void WriteString(string s)
+        {
+            WriteBinary(Encoding.UTF8.GetBytes(s));
+        }
+        public abstract void WriteBinary(byte[] b);
+
+        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 sbyte ReadByte();
+        public abstract short ReadI16();
+        public abstract int ReadI32();
+        public abstract long ReadI64();
+        public abstract double ReadDouble();
+        public virtual string ReadString()
+        {
+            var buf = ReadBinary();
+            return Encoding.UTF8.GetString(buf, 0, buf.Length);
+        }
+        public abstract byte[] ReadBinary();
+    }
+}
diff --git a/lib/csharp/src/Protocol/TProtocolDecorator.cs b/lib/csharp/src/Protocol/TProtocolDecorator.cs
new file mode 100644
index 0000000..8600002
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolDecorator.cs
@@ -0,0 +1,261 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Text;
+using Thrift.Transport;
+using System.Collections.Generic;
+
+namespace Thrift.Protocol
+{
+    /// <summary>
+    /// <see cref="TProtocolDecorator"/> forwards all requests to an enclosed <see cref="TProtocol"/> instance,
+    /// providing a way to author concise concrete decorator subclasses. While it has
+    /// no abstract methods, it is marked abstract as a reminder that by itself,
+    /// it does not modify the behaviour of the enclosed <see cref="TProtocol"/>.
+    /// <para/>
+    /// See p.175 of Design Patterns (by Gamma et al.)
+    /// </summary>
+    /// <seealso cref="TMultiplexedProtocol"/>
+    public abstract class TProtocolDecorator : TProtocol
+    {
+        private TProtocol WrappedProtocol;
+
+        /// <summary>
+        /// Encloses the specified protocol.
+        /// </summary>
+        /// <param name="protocol">All operations will be forward to this protocol.  Must be non-null.</param>
+        public TProtocolDecorator(TProtocol protocol)
+            : base(protocol.Transport)
+        {
+
+            WrappedProtocol = protocol;
+        }
+
+        public override void WriteMessageBegin(TMessage tMessage)
+        {
+            WrappedProtocol.WriteMessageBegin(tMessage);
+        }
+
+        public override void WriteMessageEnd()
+        {
+            WrappedProtocol.WriteMessageEnd();
+        }
+
+        public override void WriteStructBegin(TStruct tStruct)
+        {
+            WrappedProtocol.WriteStructBegin(tStruct);
+        }
+
+        public override void WriteStructEnd()
+        {
+            WrappedProtocol.WriteStructEnd();
+        }
+
+        public override void WriteFieldBegin(TField tField)
+        {
+            WrappedProtocol.WriteFieldBegin(tField);
+        }
+
+        public override void WriteFieldEnd()
+        {
+            WrappedProtocol.WriteFieldEnd();
+        }
+
+        public override void WriteFieldStop()
+        {
+            WrappedProtocol.WriteFieldStop();
+        }
+
+        public override void WriteMapBegin(TMap tMap)
+        {
+            WrappedProtocol.WriteMapBegin(tMap);
+        }
+
+        public override void WriteMapEnd()
+        {
+            WrappedProtocol.WriteMapEnd();
+        }
+
+        public override void WriteListBegin(TList tList)
+        {
+            WrappedProtocol.WriteListBegin(tList);
+        }
+
+        public override void WriteListEnd()
+        {
+            WrappedProtocol.WriteListEnd();
+        }
+
+        public override void WriteSetBegin(TSet tSet)
+        {
+            WrappedProtocol.WriteSetBegin(tSet);
+        }
+
+        public override void WriteSetEnd()
+        {
+            WrappedProtocol.WriteSetEnd();
+        }
+
+        public override void WriteBool(bool b)
+        {
+            WrappedProtocol.WriteBool(b);
+        }
+
+        public override void WriteByte(sbyte b)
+        {
+            WrappedProtocol.WriteByte(b);
+        }
+
+        public override void WriteI16(short i)
+        {
+            WrappedProtocol.WriteI16(i);
+        }
+
+        public override void WriteI32(int i)
+        {
+            WrappedProtocol.WriteI32(i);
+        }
+
+        public override void WriteI64(long l)
+        {
+            WrappedProtocol.WriteI64(l);
+        }
+
+        public override void WriteDouble(double v)
+        {
+            WrappedProtocol.WriteDouble(v);
+        }
+
+        public override void WriteString(string s)
+        {
+            WrappedProtocol.WriteString(s);
+        }
+
+        public override void WriteBinary(byte[] bytes)
+        {
+            WrappedProtocol.WriteBinary(bytes);
+        }
+
+        public override TMessage ReadMessageBegin()
+        {
+            return WrappedProtocol.ReadMessageBegin();
+        }
+
+        public override void ReadMessageEnd()
+        {
+            WrappedProtocol.ReadMessageEnd();
+        }
+
+        public override TStruct ReadStructBegin()
+        {
+            return WrappedProtocol.ReadStructBegin();
+        }
+
+        public override void ReadStructEnd()
+        {
+            WrappedProtocol.ReadStructEnd();
+        }
+
+        public override TField ReadFieldBegin()
+        {
+            return WrappedProtocol.ReadFieldBegin();
+        }
+
+        public override void ReadFieldEnd()
+        {
+            WrappedProtocol.ReadFieldEnd();
+        }
+
+        public override TMap ReadMapBegin()
+        {
+            return WrappedProtocol.ReadMapBegin();
+        }
+
+        public override void ReadMapEnd()
+        {
+            WrappedProtocol.ReadMapEnd();
+        }
+
+        public override TList ReadListBegin()
+        {
+            return WrappedProtocol.ReadListBegin();
+        }
+
+        public override void ReadListEnd()
+        {
+            WrappedProtocol.ReadListEnd();
+        }
+
+        public override TSet ReadSetBegin()
+        {
+            return WrappedProtocol.ReadSetBegin();
+        }
+
+        public override void ReadSetEnd()
+        {
+            WrappedProtocol.ReadSetEnd();
+        }
+
+        public override bool ReadBool()
+        {
+            return WrappedProtocol.ReadBool();
+        }
+
+        public override sbyte ReadByte()
+        {
+            return WrappedProtocol.ReadByte();
+        }
+
+        public override short ReadI16()
+        {
+            return WrappedProtocol.ReadI16();
+        }
+
+        public override int ReadI32()
+        {
+            return WrappedProtocol.ReadI32();
+        }
+
+        public override long ReadI64()
+        {
+            return WrappedProtocol.ReadI64();
+        }
+
+        public override double ReadDouble()
+        {
+            return WrappedProtocol.ReadDouble();
+        }
+
+        public override string ReadString()
+        {
+            return WrappedProtocol.ReadString();
+        }
+
+        public override byte[] ReadBinary()
+        {
+            return WrappedProtocol.ReadBinary();
+        }
+    }
+
+}
diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs
new file mode 100644
index 0000000..7bef236
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolException.cs
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift.Protocol
+{
+    public class TProtocolException : TException
+    {
+        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;
+        public const int NOT_IMPLEMENTED = 5;
+        public const int DEPTH_LIMIT = 6;
+
+        protected int type_ = UNKNOWN;
+
+        public TProtocolException()
+            : base()
+        {
+        }
+
+        public TProtocolException(int type, Exception inner = null)
+            : base(string.Empty, inner)
+        {
+            type_ = type;
+        }
+
+        public TProtocolException(int type, string message, Exception inner = null)
+            : base(message, inner)
+        {
+            type_ = type;
+        }
+
+        public TProtocolException(string message, Exception inner = null)
+            : base(message, inner)
+        {
+        }
+
+        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..71360a1
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolFactory.cs
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+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..d995c6c
--- /dev/null
+++ b/lib/csharp/src/Protocol/TProtocolUtil.cs
@@ -0,0 +1,108 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift.Protocol
+{
+    public static class TProtocolUtil
+    {
+        public static void Skip(TProtocol prot, TType type)
+        {
+            prot.IncrementRecursionDepth();
+            try
+            {
+                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:
+                        // Don't try to decode the string, just skip it.
+                        prot.ReadBinary();
+                        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;
+                    default:
+                        throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
+                }
+            }
+            finally
+            {
+                prot.DecrementRecursionDepth();
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TSet.cs b/lib/csharp/src/Protocol/TSet.cs
new file mode 100644
index 0000000..a918ab5
--- /dev/null
+++ b/lib/csharp/src/Protocol/TSet.cs
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TSet
+    {
+        private TType elementType;
+        private int count;
+
+        public TSet(TType elementType, int count)
+            :this()
+        {
+            this.elementType = elementType;
+            this.count = count;
+        }
+
+        public TSet(TList list)
+            : this(list.ElementType, list.Count)
+        {
+        }
+
+        public TType ElementType
+        {
+            get { return elementType; }
+            set { elementType = value; }
+        }
+
+        public int Count
+        {
+            get { return count; }
+            set { count = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TStruct.cs b/lib/csharp/src/Protocol/TStruct.cs
new file mode 100644
index 0000000..f4844a4
--- /dev/null
+++ b/lib/csharp/src/Protocol/TStruct.cs
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Thrift.Protocol
+{
+    public struct TStruct
+    {
+        private string name;
+
+        public TStruct(string name)
+            :this()
+        {
+            this.name = name;
+        }
+
+        public string Name
+        {
+            get { return name; }
+            set { name = value; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Protocol/TType.cs b/lib/csharp/src/Protocol/TType.cs
new file mode 100644
index 0000000..9ce915e
--- /dev/null
+++ b/lib/csharp/src/Protocol/TType.cs
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+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..2bc04f3
--- /dev/null
+++ b/lib/csharp/src/Server/TServer.cs
@@ -0,0 +1,155 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using Thrift.Protocol;
+using Thrift.Transport;
+using System.IO;
+
+namespace Thrift.Server
+{
+    public abstract class TServer
+    {
+        //Attributes
+        protected TProcessorFactory processorFactory;
+        protected TServerTransport serverTransport;
+        protected TTransportFactory inputTransportFactory;
+        protected TTransportFactory outputTransportFactory;
+        protected TProtocolFactory inputProtocolFactory;
+        protected TProtocolFactory outputProtocolFactory;
+        protected TServerEventHandler serverEventHandler = null;
+
+        //Methods
+        public void setEventHandler(TServerEventHandler seh)
+        {
+            serverEventHandler = seh;
+        }
+        public TServerEventHandler getEventHandler()
+        {
+            return serverEventHandler;
+        }
+
+        //Log delegation
+        public delegate void LogDelegate(string str);
+        private LogDelegate _logDelegate;
+        protected LogDelegate logDelegate
+        {
+            get { return _logDelegate; }
+            set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
+        }
+        protected static void DefaultLogDelegate(string s)
+        {
+            Console.Error.WriteLine(s);
+        }
+
+        //Construction
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport)
+          : this(processor, serverTransport,
+             new TTransportFactory(),
+             new TTransportFactory(),
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             DefaultLogDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+                TServerTransport serverTransport,
+                LogDelegate logDelegate)
+          : this(processor,
+             serverTransport,
+             new TTransportFactory(),
+             new TTransportFactory(),
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             logDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory)
+          : this(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+             DefaultLogDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory,
+                  TProtocolFactory protocolFactory)
+          : this(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             protocolFactory,
+             protocolFactory,
+               DefaultLogDelegate)
+        {
+        }
+
+        public TServer(TProcessor processor,
+            TServerTransport serverTransport,
+            TTransportFactory inputTransportFactory,
+            TTransportFactory outputTransportFactory,
+            TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory,
+            LogDelegate logDelegate)
+        {
+            this.processorFactory = new TSingletonProcessorFactory(processor);
+            this.serverTransport = serverTransport;
+            this.inputTransportFactory = inputTransportFactory;
+            this.outputTransportFactory = outputTransportFactory;
+            this.inputProtocolFactory = inputProtocolFactory;
+            this.outputProtocolFactory = outputProtocolFactory;
+            this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
+        }
+
+        public TServer(TProcessorFactory processorFactory,
+                  TServerTransport serverTransport,
+                  TTransportFactory inputTransportFactory,
+                  TTransportFactory outputTransportFactory,
+                  TProtocolFactory inputProtocolFactory,
+                  TProtocolFactory outputProtocolFactory,
+                  LogDelegate logDelegate)
+        {
+            this.processorFactory = processorFactory;
+            this.serverTransport = serverTransport;
+            this.inputTransportFactory = inputTransportFactory;
+            this.outputTransportFactory = outputTransportFactory;
+            this.inputProtocolFactory = inputProtocolFactory;
+            this.outputProtocolFactory = outputProtocolFactory;
+            this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
+        }
+
+        //Abstract Interface
+        public abstract void Serve();
+        public abstract void Stop();
+    }
+}
diff --git a/lib/csharp/src/Server/TServerEventHandler.cs b/lib/csharp/src/Server/TServerEventHandler.cs
new file mode 100644
index 0000000..e81efc6
--- /dev/null
+++ b/lib/csharp/src/Server/TServerEventHandler.cs
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift.Server
+{
+    /// <summary>
+    /// Interface implemented by server users to handle events from the server.
+    /// </summary>
+    public interface TServerEventHandler
+    {
+        /// <summary>
+        /// Called before the server begins.
+        /// </summary>
+        void preServe();
+
+        /// <summary>
+        /// Called when a new client has connected and is about to being processing.
+        /// </summary>
+        object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
+
+        /// <summary>
+        /// Called when a client has finished request-handling to delete server context.
+        /// </summary>
+        void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
+
+        /// <summary>
+        /// Called when a client is about to call the processor.
+        /// </summary>
+        void processContext(object serverContext, Thrift.Transport.TTransport transport);
+    };
+}
diff --git a/lib/csharp/src/Server/TSimpleServer.cs b/lib/csharp/src/Server/TSimpleServer.cs
new file mode 100644
index 0000000..4e7ea96
--- /dev/null
+++ b/lib/csharp/src/Server/TSimpleServer.cs
@@ -0,0 +1,180 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using Thrift.Transport;
+using Thrift.Protocol;
+
+namespace Thrift.Server
+{
+    /// <summary>
+    /// Simple single-threaded server for testing.
+    /// </summary>
+    public class TSimpleServer : TServer
+    {
+        private bool stop = false;
+
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport)
+          : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
+        {
+        }
+
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  LogDelegate logDel)
+          : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
+        {
+        }
+
+        public TSimpleServer(TProcessor processor,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory)
+          : base(processor,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             new TBinaryProtocol.Factory(),
+             new TBinaryProtocol.Factory(),
+               DefaultLogDelegate)
+        {
+        }
+
+        public TSimpleServer(TProcessor processor,
+            TServerTransport serverTransport,
+            TTransportFactory transportFactory,
+            TProtocolFactory protocolFactory)
+            : base(processor,
+               serverTransport,
+               transportFactory,
+               transportFactory,
+               protocolFactory,
+               protocolFactory,
+               DefaultLogDelegate)
+        {
+        }
+
+        public TSimpleServer(TProcessorFactory processorFactory,
+                  TServerTransport serverTransport,
+                  TTransportFactory transportFactory,
+                  TProtocolFactory protocolFactory)
+          : base(processorFactory,
+             serverTransport,
+             transportFactory,
+             transportFactory,
+             protocolFactory,
+             protocolFactory,
+             DefaultLogDelegate)
+        {
+        }
+
+        public override void Serve()
+        {
+            try
+            {
+                serverTransport.Listen();
+            }
+            catch (TTransportException ttx)
+            {
+                logDelegate(ttx.ToString());
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
+            if (serverEventHandler != null)
+                serverEventHandler.preServe();
+
+            while (!stop)
+            {
+                TProcessor processor = null;
+                TTransport client = null;
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    using (client = serverTransport.Accept())
+                    {
+                        processor = processorFactory.GetProcessor(client);
+                        if (client != null)
+                        {
+                            using (inputTransport = inputTransportFactory.GetTransport(client))
+                            {
+                                using (outputTransport = outputTransportFactory.GetTransport(client))
+                                {
+                                    inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                                    outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                                    //Recover event handler (if any) and fire createContext server event when a client connects
+                                    if (serverEventHandler != null)
+                                        connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                                    //Process client requests until client disconnects
+                                    while (!stop)
+                                    {
+                                        if (!inputTransport.Peek())
+                                            break;
+
+                                        //Fire processContext server event
+                                        //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                                        //That is to say it may be many minutes between the event firing and the client request
+                                        //actually arriving or the client may hang up without ever makeing a request.
+                                        if (serverEventHandler != null)
+                                            serverEventHandler.processContext(connectionContext, inputTransport);
+                                        //Process client request (blocks until transport is readable)
+                                        if (!processor.Process(inputProtocol, outputProtocol))
+                                            break;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        logDelegate(ttx.ToString());
+                    }
+                }
+                catch (Exception x)
+                {
+                    //Unexpected
+                    logDelegate(x.ToString());
+                }
+
+                //Fire deleteContext server event after client disconnects
+                if (serverEventHandler != null)
+                    serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+            }
+        }
+
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+        }
+    }
+}
diff --git a/lib/csharp/src/Server/TThreadPoolServer.cs b/lib/csharp/src/Server/TThreadPoolServer.cs
new file mode 100644
index 0000000..a494ce7
--- /dev/null
+++ b/lib/csharp/src/Server/TThreadPoolServer.cs
@@ -0,0 +1,295 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+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 = -1;  // use .NET ThreadPool defaults
+        private const int DEFAULT_MAX_THREADS = -1;  // use .NET ThreadPool defaults
+        private volatile bool stop = false;
+
+        public struct Configuration
+        {
+            public int MinWorkerThreads;
+            public int MaxWorkerThreads;
+            public int MinIOThreads;
+            public int MaxIOThreads;
+
+            public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
+            {
+                MinWorkerThreads = min;
+                MaxWorkerThreads = max;
+                MinIOThreads = min;
+                MaxIOThreads = max;
+            }
+
+            public Configuration(int minWork, int maxWork, int minIO, int maxIO)
+            {
+                MinWorkerThreads = minWork;
+                MaxWorkerThreads = maxWork;
+                MinIOThreads = minIO;
+                MaxIOThreads = maxIO;
+            }
+        }
+
+        public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             new Configuration(), DefaultLogDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             new Configuration(), logDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessor processor,
+         TServerTransport serverTransport,
+         TTransportFactory transportFactory,
+         TProtocolFactory protocolFactory)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+               transportFactory, transportFactory,
+               protocolFactory, protocolFactory,
+               new Configuration(), DefaultLogDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory transportFactory,
+                     TProtocolFactory protocolFactory)
+            : this(processorFactory, serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             new Configuration(), DefaultLogDelegate)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
+            : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+             inputProtocolFactory, outputProtocolFactory,
+             new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
+             logDel)
+        {
+        }
+
+        public TThreadPoolServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     Configuration threadConfig,
+                     LogDelegate logDel)
+            : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+            inputProtocolFactory, outputProtocolFactory, logDel)
+        {
+            lock (typeof(TThreadPoolServer))
+            {
+                if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
+                {
+                    int work, comm;
+                    ThreadPool.GetMaxThreads(out work, out comm);
+                    if (threadConfig.MaxWorkerThreads > 0)
+                        work = threadConfig.MaxWorkerThreads;
+                    if (threadConfig.MaxIOThreads > 0)
+                        comm = threadConfig.MaxIOThreads;
+                    if (!ThreadPool.SetMaxThreads(work, comm))
+                        throw new Exception("Error: could not SetMaxThreads in ThreadPool");
+                }
+
+                if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
+                {
+                    int work, comm;
+                    ThreadPool.GetMinThreads(out work, out comm);
+                    if (threadConfig.MinWorkerThreads > 0)
+                        work = threadConfig.MinWorkerThreads;
+                    if (threadConfig.MinIOThreads > 0)
+                        comm = threadConfig.MinIOThreads;
+                    if (!ThreadPool.SetMinThreads(work, comm))
+                        throw new Exception("Error: could not SetMinThreads in ThreadPool");
+                }
+            }
+        }
+
+
+        /// <summary>
+        /// Use new ThreadPool thread for each new client connection.
+        /// </summary>
+        public override void Serve()
+        {
+            try
+            {
+                serverTransport.Listen();
+            }
+            catch (TTransportException ttx)
+            {
+                logDelegate("Error, could not listen on ServerTransport: " + ttx);
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
+            if (serverEventHandler != null)
+                serverEventHandler.preServe();
+
+            while (!stop)
+            {
+                int failureCount = 0;
+                try
+                {
+                    TTransport client = serverTransport.Accept();
+                    ThreadPool.QueueUserWorkItem(this.Execute, client);
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        ++failureCount;
+                        logDelegate(ttx.ToString());
+                    }
+
+                }
+            }
+
+            if (stop)
+            {
+                try
+                {
+                    serverTransport.Close();
+                }
+                catch (TTransportException ttx)
+                {
+                    logDelegate("TServerTransport failed on close: " + ttx.Message);
+                }
+                stop = false;
+            }
+        }
+
+        /// <summary>
+        /// Loops on processing a client forever
+        /// threadContext will be a TTransport instance
+        /// </summary>
+        /// <param name="threadContext"></param>
+        private void Execute(object threadContext)
+        {
+            using (TTransport client = (TTransport)threadContext)
+            {
+                TProcessor processor = processorFactory.GetProcessor(client, this);
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    try
+                    {
+                        inputTransport = inputTransportFactory.GetTransport(client);
+                        outputTransport = outputTransportFactory.GetTransport(client);
+                        inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                        outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                        //Recover event handler (if any) and fire createContext server event when a client connects
+                        if (serverEventHandler != null)
+                            connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                        //Process client requests until client disconnects
+                        while (!stop)
+                        {
+                            if (!inputTransport.Peek())
+                                break;
+
+                            //Fire processContext server event
+                            //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                            //That is to say it may be many minutes between the event firing and the client request
+                            //actually arriving or the client may hang up without ever makeing a request.
+                            if (serverEventHandler != null)
+                                serverEventHandler.processContext(connectionContext, inputTransport);
+                            //Process client request (blocks until transport is readable)
+                            if (!processor.Process(inputProtocol, outputProtocol))
+                                break;
+                        }
+                    }
+                    catch (TTransportException)
+                    {
+                        //Usually a client disconnect, expected
+                    }
+                    catch (Exception x)
+                    {
+                        //Unexpected
+                        logDelegate("Error: " + x);
+                    }
+
+                    //Fire deleteContext server event after client disconnects
+                    if (serverEventHandler != null)
+                        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+
+                }
+                finally
+                {
+                    //Close transports
+                    if (inputTransport != null)
+                        inputTransport.Close();
+                    if (outputTransport != null)
+                        outputTransport.Close();
+
+                    // disposable stuff should be disposed
+                    if (inputProtocol != null)
+                        inputProtocol.Dispose();
+                    if (outputProtocol != null)
+                        outputProtocol.Dispose();
+                    if (inputTransport != null)
+                        inputTransport.Dispose();
+                    if (outputTransport != null)
+                        outputTransport.Dispose();
+                }
+            }
+        }
+
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+        }
+    }
+}
diff --git a/lib/csharp/src/Server/TThreadedServer.cs b/lib/csharp/src/Server/TThreadedServer.cs
new file mode 100644
index 0000000..cc051a3
--- /dev/null
+++ b/lib/csharp/src/Server/TThreadedServer.cs
@@ -0,0 +1,282 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Thrift.Collections;
+using Thrift.Protocol;
+using Thrift.Transport;
+
+namespace Thrift.Server
+{
+    /// <summary>
+    /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests.
+    /// </summary>
+    public class TThreadedServer : TServer
+    {
+        private const int DEFAULT_MAX_THREADS = 100;
+        private volatile bool stop = false;
+        private readonly int maxThreads;
+
+        private Queue<TTransport> clientQueue;
+        private THashSet<Thread> clientThreads;
+        private object clientLock;
+        private Thread workerThread;
+
+        public int ClientThreadsCount
+        {
+            get { return clientThreads.Count; }
+        }
+
+        public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
+        {
+        }
+
+        public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             new TTransportFactory(), new TTransportFactory(),
+             new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
+             DEFAULT_MAX_THREADS, logDelegate)
+        {
+        }
+
+
+        public TThreadedServer(TProcessor processor,
+                     TServerTransport serverTransport,
+                     TTransportFactory transportFactory,
+                     TProtocolFactory protocolFactory)
+            : this(new TSingletonProcessorFactory(processor), serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
+        {
+        }
+
+        public TThreadedServer(TProcessorFactory processorFactory,
+               TServerTransport serverTransport,
+               TTransportFactory transportFactory,
+               TProtocolFactory protocolFactory)
+            : this(processorFactory, serverTransport,
+             transportFactory, transportFactory,
+             protocolFactory, protocolFactory,
+             DEFAULT_MAX_THREADS, DefaultLogDelegate)
+        {
+        }
+        public TThreadedServer(TProcessorFactory processorFactory,
+                     TServerTransport serverTransport,
+                     TTransportFactory inputTransportFactory,
+                     TTransportFactory outputTransportFactory,
+                     TProtocolFactory inputProtocolFactory,
+                     TProtocolFactory outputProtocolFactory,
+                     int maxThreads, LogDelegate logDel)
+          : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
+              inputProtocolFactory, outputProtocolFactory, logDel)
+        {
+            this.maxThreads = maxThreads;
+            clientQueue = new Queue<TTransport>();
+            clientLock = new object();
+            clientThreads = new THashSet<Thread>();
+        }
+
+        /// <summary>
+        /// Use new Thread for each new client connection. block until numConnections &lt; maxThreads.
+        /// </summary>
+        public override void Serve()
+        {
+            try
+            {
+                //start worker thread
+                workerThread = new Thread(new ThreadStart(Execute));
+                workerThread.Start();
+                serverTransport.Listen();
+            }
+            catch (TTransportException ttx)
+            {
+                logDelegate("Error, could not listen on ServerTransport: " + ttx);
+                return;
+            }
+
+            //Fire the preServe server event when server is up but before any client connections
+            if (serverEventHandler != null)
+                serverEventHandler.preServe();
+
+            while (!stop)
+            {
+                int failureCount = 0;
+                try
+                {
+                    TTransport client = serverTransport.Accept();
+                    lock (clientLock)
+                    {
+                        clientQueue.Enqueue(client);
+                        Monitor.Pulse(clientLock);
+                    }
+                }
+                catch (TTransportException ttx)
+                {
+                    if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
+                    {
+                        ++failureCount;
+                        logDelegate(ttx.ToString());
+                    }
+
+                }
+            }
+
+            if (stop)
+            {
+                try
+                {
+                    serverTransport.Close();
+                }
+                catch (TTransportException ttx)
+                {
+                    logDelegate("TServeTransport failed on close: " + ttx.Message);
+                }
+                stop = false;
+            }
+        }
+
+        /// <summary>
+        /// Loops on processing a client forever
+        /// </summary>
+        private void Execute()
+        {
+            while (!stop)
+            {
+                TTransport client;
+                Thread t;
+                lock (clientLock)
+                {
+                    //don't dequeue if too many connections
+                    while (clientThreads.Count >= maxThreads)
+                    {
+                        Monitor.Wait(clientLock);
+                    }
+
+                    while (clientQueue.Count == 0)
+                    {
+                        Monitor.Wait(clientLock);
+                    }
+
+                    client = clientQueue.Dequeue();
+                    t = new Thread(new ParameterizedThreadStart(ClientWorker));
+                    clientThreads.Add(t);
+                }
+                //start processing requests from client on new thread
+                t.Start(client);
+            }
+        }
+
+        private void ClientWorker(object context)
+        {
+            using (TTransport client = (TTransport)context)
+            {
+                TProcessor processor = processorFactory.GetProcessor(client);
+                TTransport inputTransport = null;
+                TTransport outputTransport = null;
+                TProtocol inputProtocol = null;
+                TProtocol outputProtocol = null;
+                object connectionContext = null;
+                try
+                {
+                    try
+                    {
+                        inputTransport = inputTransportFactory.GetTransport(client);
+                        outputTransport = outputTransportFactory.GetTransport(client);
+                        inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
+                        outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
+
+                        //Recover event handler (if any) and fire createContext server event when a client connects
+                        if (serverEventHandler != null)
+                            connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
+
+                        //Process client requests until client disconnects
+                        while (!stop)
+                        {
+                            if (!inputTransport.Peek())
+                                break;
+
+                            //Fire processContext server event
+                            //N.B. This is the pattern implemented in C++ and the event fires provisionally.
+                            //That is to say it may be many minutes between the event firing and the client request
+                            //actually arriving or the client may hang up without ever makeing a request.
+                            if (serverEventHandler != null)
+                                serverEventHandler.processContext(connectionContext, inputTransport);
+                            //Process client request (blocks until transport is readable)
+                            if (!processor.Process(inputProtocol, outputProtocol))
+                                break;
+                        }
+                    }
+                    catch (TTransportException)
+                    {
+                        //Usually a client disconnect, expected
+                    }
+                    catch (Exception x)
+                    {
+                        //Unexpected
+                        logDelegate("Error: " + x);
+                    }
+
+                    //Fire deleteContext server event after client disconnects
+                    if (serverEventHandler != null)
+                        serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
+
+                    lock (clientLock)
+                    {
+                        clientThreads.Remove(Thread.CurrentThread);
+                        Monitor.Pulse(clientLock);
+                    }
+
+                }
+                finally
+                {
+                    //Close transports
+                    if (inputTransport != null)
+                        inputTransport.Close();
+                    if (outputTransport != null)
+                        outputTransport.Close();
+
+                    // disposable stuff should be disposed
+                    if (inputProtocol != null)
+                        inputProtocol.Dispose();
+                    if (outputProtocol != null)
+                        outputProtocol.Dispose();
+                }
+            }
+        }
+
+        public override void Stop()
+        {
+            stop = true;
+            serverTransport.Close();
+            //clean up all the threads myself
+            workerThread.Abort();
+            foreach (Thread t in clientThreads)
+            {
+                t.Abort();
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/TApplicationException.cs b/lib/csharp/src/TApplicationException.cs
new file mode 100644
index 0000000..8dd7ae5
--- /dev/null
+++ b/lib/csharp/src/TApplicationException.cs
@@ -0,0 +1,146 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using Thrift.Protocol;
+
+namespace Thrift
+{
+    public class TApplicationException : TException
+    {
+        protected ExceptionType type;
+
+        public TApplicationException()
+        {
+        }
+
+        public TApplicationException(ExceptionType type)
+        {
+            this.type = type;
+        }
+
+        public TApplicationException(ExceptionType type, string message)
+            : base(message, null) // TApplicationException is serializable, but we never serialize InnerException
+        {
+            this.type = type;
+        }
+
+        public static TApplicationException Read(TProtocol iprot)
+        {
+            TField field;
+
+            string message = null;
+            ExceptionType type = ExceptionType.Unknown;
+
+            iprot.ReadStructBegin();
+            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,
+            InternalError,
+            ProtocolError,
+            InvalidTransform,
+            InvalidProtocol,
+            UnsupportedClientType
+        }
+
+        public ExceptionType Type
+        {
+            get { return type; }
+        }
+    }
+}
diff --git a/lib/csharp/src/TAsyncProcessor.cs b/lib/csharp/src/TAsyncProcessor.cs
new file mode 100644
index 0000000..ab43225
--- /dev/null
+++ b/lib/csharp/src/TAsyncProcessor.cs
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System.Threading.Tasks;
+using Thrift.Protocol;
+
+namespace Thrift
+{
+    /// <summary>
+    /// Processes a message asynchronously.
+    /// </summary>
+    public interface TAsyncProcessor
+    {
+        /// <summary>
+        /// Processes the next part of the message.
+        /// </summary>
+        /// <param name="iprot">The input protocol.</param>
+        /// <param name="oprot">The output protocol.</param>
+        /// <returns>true if there's more to process, false otherwise.</returns>
+        Task<bool> ProcessAsync(TProtocol iprot, TProtocol oprot);
+    }
+}
diff --git a/lib/csharp/src/TControllingHandler.cs b/lib/csharp/src/TControllingHandler.cs
new file mode 100644
index 0000000..7b5203a
--- /dev/null
+++ b/lib/csharp/src/TControllingHandler.cs
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using Thrift.Server;
+
+namespace Thrift
+{
+    public interface TControllingHandler
+    {
+        TServer server { get; set; }
+    }
+}
diff --git a/lib/csharp/src/TException.cs b/lib/csharp/src/TException.cs
new file mode 100644
index 0000000..b9fae6e
--- /dev/null
+++ b/lib/csharp/src/TException.cs
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift
+{
+    public class TException : Exception
+    {
+        public TException()
+        {
+        }
+
+        public TException(string message, Exception inner = null)
+            : base(message, inner)
+        {
+        }
+
+    }
+}
diff --git a/lib/csharp/src/TProcessor.cs b/lib/csharp/src/TProcessor.cs
new file mode 100644
index 0000000..71ce755
--- /dev/null
+++ b/lib/csharp/src/TProcessor.cs
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using Thrift.Protocol;
+
+namespace Thrift
+{
+    public interface TProcessor
+    {
+        bool Process(TProtocol iprot, TProtocol oprot);
+    }
+}
diff --git a/lib/csharp/src/TProcessorFactory.cs b/lib/csharp/src/TProcessorFactory.cs
new file mode 100644
index 0000000..fdf631b
--- /dev/null
+++ b/lib/csharp/src/TProcessorFactory.cs
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using Thrift.Server;
+using Thrift.Transport;
+
+namespace Thrift
+{
+    public interface TProcessorFactory
+    {
+        TProcessor GetProcessor(TTransport trans, TServer server = null);
+    }
+}
diff --git a/lib/csharp/src/TPrototypeProcessorFactory.cs b/lib/csharp/src/TPrototypeProcessorFactory.cs
new file mode 100644
index 0000000..0b47261
--- /dev/null
+++ b/lib/csharp/src/TPrototypeProcessorFactory.cs
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Thrift.Server;
+using Thrift.Transport;
+
+namespace Thrift
+{
+    public class TPrototypeProcessorFactory<P, H> : TProcessorFactory where P : TProcessor
+    {
+        object[] handlerArgs = null;
+
+        public TPrototypeProcessorFactory()
+        {
+            handlerArgs = new object[0];
+        }
+
+        public TPrototypeProcessorFactory(params object[] handlerArgs)
+        {
+            this.handlerArgs = handlerArgs;
+        }
+
+        public TProcessor GetProcessor(TTransport trans, TServer server = null)
+        {
+            H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs);
+
+            TControllingHandler handlerServerRef = handler as TControllingHandler;
+            if (handlerServerRef != null)
+            {
+                handlerServerRef.server = server;
+            }
+            return Activator.CreateInstance(typeof(P), new object[] { handler }) as TProcessor;
+        }
+    }
+}
diff --git a/lib/csharp/src/TSingletonProcessorFactory.cs b/lib/csharp/src/TSingletonProcessorFactory.cs
new file mode 100644
index 0000000..ed2897b
--- /dev/null
+++ b/lib/csharp/src/TSingletonProcessorFactory.cs
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Thrift.Server;
+using Thrift.Transport;
+
+namespace Thrift
+{
+    public class TSingletonProcessorFactory : TProcessorFactory
+    {
+        private readonly TProcessor processor_;
+
+        public TSingletonProcessorFactory(TProcessor processor)
+        {
+            processor_ = processor;
+        }
+
+        public TProcessor GetProcessor(TTransport trans, TServer server = null)
+        {
+            return processor_;
+        }
+    }
+}
diff --git a/lib/csharp/src/Thrift.45.csproj b/lib/csharp/src/Thrift.45.csproj
new file mode 100644
index 0000000..146e7f8
--- /dev/null
+++ b/lib/csharp/src/Thrift.45.csproj
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{EBCE35DA-CF6A-42BC-A357-A9C09B534299}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Thrift</RootNamespace>
+    <AssemblyName>Thrift45</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>portable</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;NET45</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>portable</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;NET45</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>thrift.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Collections\TCollections.cs" />
+    <Compile Include="Collections\THashSet.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Protocol\TAbstractBase.cs" />
+    <Compile Include="Protocol\TBase.cs" />
+    <Compile Include="Protocol\TBase64Utils.cs" />
+    <Compile Include="Protocol\TBinaryProtocol.cs" />
+    <Compile Include="Protocol\TCompactProtocol.cs" />
+    <Compile Include="Protocol\TField.cs" />
+    <Compile Include="Protocol\TJSONProtocol.cs" />
+    <Compile Include="Protocol\TList.cs" />
+    <Compile Include="Protocol\TMap.cs" />
+    <Compile Include="Protocol\TMessage.cs" />
+    <Compile Include="Protocol\TMessageType.cs" />
+    <Compile Include="Protocol\TMultiplexedProcessor.cs" />
+    <Compile Include="Protocol\TMultiplexedProtocol.cs" />
+    <Compile Include="Protocol\TProtocol.cs" />
+    <Compile Include="Protocol\TProtocolDecorator.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\TServerEventHandler.cs" />
+    <Compile Include="Server\TSimpleServer.cs" />
+    <Compile Include="Server\TThreadedServer.cs" />
+    <Compile Include="Server\TThreadPoolServer.cs" />
+    <Compile Include="TApplicationException.cs" />
+    <Compile Include="TAsyncProcessor.cs" />
+    <Compile Include="TControllingHandler.cs" />
+    <Compile Include="TException.cs" />
+    <Compile Include="TProcessor.cs" />
+    <Compile Include="TProcessorFactory.cs" />
+    <Compile Include="TPrototypeProcessorFactory.cs" />
+    <Compile Include="Transport\TBufferedTransport.cs" />
+    <Compile Include="Transport\TFramedTransport.cs" />
+    <Compile Include="Transport\THttpClient.cs" />
+    <Compile Include="Transport\THttpHandler.cs" />
+    <Compile Include="Transport\THttpTaskAsyncHandler.cs" />
+    <Compile Include="Transport\TMemoryBuffer.cs" />
+    <Compile Include="Transport\TNamedPipeClientTransport.cs" />
+    <Compile Include="Transport\TNamedPipeServerTransport.cs" />
+    <Compile Include="Transport\TServerSocket.cs" />
+    <Compile Include="Transport\TServerTransport.cs" />
+    <Compile Include="Transport\TSilverlightSocket.cs" />
+    <Compile Include="Transport\TSocket.cs" />
+    <Compile Include="Transport\TSocketVersionizer.cs" />
+    <Compile Include="Transport\TStreamTransport.cs" />
+    <Compile Include="Transport\TTLSServerSocket.cs" />
+    <Compile Include="Transport\TTLSSocket.cs" />
+    <Compile Include="Transport\TTransport.cs" />
+    <Compile Include="Transport\TTransportException.cs" />
+    <Compile Include="Transport\TTransportFactory.cs" />
+    <Compile Include="TSingletonProcessorFactory.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Server\Collections\" />
+    <Folder Include="Server\Protocol\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="thrift.snk" />
+  </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/Thrift.csproj b/lib/csharp/src/Thrift.csproj
new file mode 100644
index 0000000..1305482
--- /dev/null
+++ b/lib/csharp/src/Thrift.csproj
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<Project ToolsVersion="4.0" 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>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation />
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>0.14.0.0</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>portable</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>portable</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>
+    </DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>thrift.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Web" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Collections\TCollections.cs" />
+    <Compile Include="Collections\THashSet.cs" />
+    <Compile Include="Net35\ExtensionsNet35.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Protocol\TAbstractBase.cs" />
+    <Compile Include="Protocol\TBase.cs" />
+    <Compile Include="Protocol\TBase64Utils.cs" />
+    <Compile Include="Protocol\TBinaryProtocol.cs" />
+    <Compile Include="Protocol\TCompactProtocol.cs" />
+    <Compile Include="Protocol\TField.cs" />
+    <Compile Include="Protocol\TJSONProtocol.cs" />
+    <Compile Include="Protocol\TList.cs" />
+    <Compile Include="Protocol\TMap.cs" />
+    <Compile Include="Protocol\TMessage.cs" />
+    <Compile Include="Protocol\TMessageType.cs" />
+    <Compile Include="Protocol\TMultiplexedProcessor.cs" />
+    <Compile Include="Protocol\TMultiplexedProtocol.cs" />
+    <Compile Include="Protocol\TProtocol.cs" />
+    <Compile Include="Protocol\TProtocolDecorator.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\TServerEventHandler.cs" />
+    <Compile Include="Server\TSimpleServer.cs" />
+    <Compile Include="Server\TThreadedServer.cs" />
+    <Compile Include="Server\TThreadPoolServer.cs" />
+    <Compile Include="TApplicationException.cs" />
+    <Compile Include="TControllingHandler.cs" />
+    <Compile Include="TException.cs" />
+    <Compile Include="TProcessor.cs" />
+    <Compile Include="TProcessorFactory.cs" />
+    <Compile Include="TPrototypeProcessorFactory.cs" />
+    <Compile Include="Transport\TBufferedTransport.cs" />
+    <Compile Include="Transport\TFramedTransport.cs" />
+    <Compile Include="Transport\THttpClient.cs" />
+    <Compile Include="Transport\THttpHandler.cs" />
+    <Compile Include="Transport\TMemoryBuffer.cs" />
+    <Compile Include="Transport\TNamedPipeClientTransport.cs" />
+    <Compile Include="Transport\TNamedPipeServerTransport.cs" />
+    <Compile Include="Transport\TServerSocket.cs" />
+    <Compile Include="Transport\TServerTransport.cs" />
+    <Compile Include="Transport\TSocket.cs" />
+    <Compile Include="Transport\TSocketVersionizer.cs" />
+    <Compile Include="Transport\TStreamTransport.cs" />
+    <Compile Include="Transport\TTLSServerSocket.cs" />
+    <Compile Include="Transport\TTLSSocket.cs" />
+    <Compile Include="Transport\TTransport.cs" />
+    <Compile Include="Transport\TTransportException.cs" />
+    <Compile Include="Transport\TTransportFactory.cs" />
+    <Compile Include="TSingletonProcessorFactory.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
+      <Visible>False</Visible>
+      <ProductName>Windows Installer 3.1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="thrift.snk" />
+  </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..a29e468
--- /dev/null
+++ b/lib/csharp/src/Thrift.sln
@@ -0,0 +1,47 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "..\test\ThriftTest\ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMSBuildTask", "..\ThriftMSBuildTask\ThriftMSBuildTask.csproj", "{EC0A0231-66EA-4593-A792-C6CA3BB8668E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.45", "Thrift.45.csproj", "{EBCE35DA-CF6A-42BC-A357-A9C09B534299}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMVCTest", "..\test\ThriftMVCTest\ThriftMVCTest.csproj", "{891B4487-C7BA-427E-BBC8-4C596C229A10}"
+EndProject
+Global
+	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
+		{EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.Build.0 = Release|Any CPU
+		{891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		        StartupItem = Thrift.csproj
+	EndGlobalSection
+EndGlobal
diff --git a/lib/csharp/src/Transport/TBufferedTransport.cs b/lib/csharp/src/Transport/TBufferedTransport.cs
new file mode 100644
index 0000000..8870988
--- /dev/null
+++ b/lib/csharp/src/Transport/TBufferedTransport.cs
@@ -0,0 +1,194 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.IO;
+
+namespace Thrift.Transport
+{
+    public class TBufferedTransport : TTransport, IDisposable
+    {
+        private readonly int bufSize;
+        private readonly MemoryStream inputBuffer = new MemoryStream(0);
+        private readonly MemoryStream outputBuffer = new MemoryStream(0);
+        private readonly TTransport transport;
+
+        public TBufferedTransport(TTransport transport, int bufSize = 1024)
+        {
+            if (transport == null)
+                throw new ArgumentNullException("transport");
+            if (bufSize <= 0)
+                throw new ArgumentException("bufSize", "Buffer size must be a positive number.");
+            this.transport = transport;
+            this.bufSize = bufSize;
+        }
+
+        public TTransport UnderlyingTransport
+        {
+            get
+            {
+                CheckNotDisposed();
+                return transport;
+            }
+        }
+
+        public override bool IsOpen
+        {
+            get
+            {
+                // We can legitimately throw here but be nice a bit.
+                // CheckNotDisposed();
+                return !_IsDisposed && transport.IsOpen;
+            }
+        }
+
+        public override void Open()
+        {
+            CheckNotDisposed();
+            transport.Open();
+        }
+
+        public override void Close()
+        {
+            CheckNotDisposed();
+            transport.Close();
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            CheckNotDisposed();
+            ValidateBufferArgs(buf, off, len);
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+
+            if (inputBuffer.Capacity < bufSize)
+                inputBuffer.Capacity = bufSize;
+
+            while (true)
+            {
+                int got = inputBuffer.Read(buf, off, len);
+                if (got > 0)
+                    return got;
+
+                inputBuffer.Seek(0, SeekOrigin.Begin);
+                inputBuffer.SetLength(inputBuffer.Capacity);
+                int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length);
+                inputBuffer.SetLength(filled);
+                if (filled == 0)
+                    return 0;
+            }
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            CheckNotDisposed();
+            ValidateBufferArgs(buf, off, len);
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            // Relative offset from "off" argument
+            int offset = 0;
+            if (outputBuffer.Length > 0)
+            {
+                int capa = (int)(outputBuffer.Capacity - outputBuffer.Length);
+                int writeSize = capa <= len ? capa : len;
+                outputBuffer.Write(buf, off, writeSize);
+                offset += writeSize;
+                if (writeSize == capa)
+                {
+                    transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length);
+                    outputBuffer.SetLength(0);
+                }
+            }
+            while (len - offset >= bufSize)
+            {
+                transport.Write(buf, off + offset, bufSize);
+                offset += bufSize;
+            }
+            int remain = len - offset;
+            if (remain > 0)
+            {
+                if (outputBuffer.Capacity < bufSize)
+                    outputBuffer.Capacity = bufSize;
+                outputBuffer.Write(buf, off + offset, remain);
+            }
+        }
+
+        private void InternalFlush()
+        {
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            if (outputBuffer.Length > 0)
+            {
+                transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length);
+                outputBuffer.SetLength(0);
+            }
+        }
+
+        public override void Flush()
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            transport.Flush();
+        }
+
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            return transport.BeginFlush( callback, state);
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            transport.EndFlush( asyncResult);
+        }
+
+
+
+        protected void CheckNotDisposed()
+        {
+            if (_IsDisposed)
+                throw new ObjectDisposedException("TBufferedTransport");
+        }
+
+        #region " IDisposable Support "
+        protected bool _IsDisposed { get; private set; }
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (inputBuffer != null)
+                        inputBuffer.Dispose();
+                    if (outputBuffer != null)
+                        outputBuffer.Dispose();
+                    if (transport != null)
+                        transport.Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs
new file mode 100644
index 0000000..a746a32
--- /dev/null
+++ b/lib/csharp/src/Transport/TFramedTransport.cs
@@ -0,0 +1,205 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+using System;
+using System.IO;
+
+namespace Thrift.Transport
+{
+    public class TFramedTransport : TTransport, IDisposable
+    {
+        private readonly TTransport transport;
+        private readonly MemoryStream writeBuffer = new MemoryStream(1024);
+        private readonly MemoryStream readBuffer = new MemoryStream(1024);
+
+        private const int HeaderSize = 4;
+        private readonly byte[] headerBuf = new byte[HeaderSize];
+
+        public class Factory : TTransportFactory
+        {
+            public override TTransport GetTransport(TTransport trans)
+            {
+                return new TFramedTransport(trans);
+            }
+        }
+
+        public TFramedTransport(TTransport transport)
+        {
+            if (transport == null)
+                throw new ArgumentNullException("transport");
+            this.transport = transport;
+            InitWriteBuffer();
+        }
+
+        public override void Open()
+        {
+            CheckNotDisposed();
+            transport.Open();
+        }
+
+        public override bool IsOpen
+        {
+            get
+            {
+                // We can legitimately throw here but be nice a bit.
+                // CheckNotDisposed();
+                return !_IsDisposed && transport.IsOpen;
+            }
+        }
+
+        public override void Close()
+        {
+            CheckNotDisposed();
+            transport.Close();
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            CheckNotDisposed();
+            ValidateBufferArgs(buf, off, len);
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            int got = readBuffer.Read(buf, off, len);
+            if (got > 0)
+            {
+                return got;
+            }
+
+            // Read another frame of data
+            ReadFrame();
+
+            return readBuffer.Read(buf, off, len);
+        }
+
+        private void ReadFrame()
+        {
+            transport.ReadAll(headerBuf, 0, HeaderSize);
+            int size = DecodeFrameSize(headerBuf);
+
+            readBuffer.SetLength(size);
+            readBuffer.Seek(0, SeekOrigin.Begin);
+            byte[] buff = readBuffer.GetBuffer();
+            transport.ReadAll(buff, 0, size);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            CheckNotDisposed();
+            ValidateBufferArgs(buf, off, len);
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            if (writeBuffer.Length + (long)len > (long)int.MaxValue)
+                Flush();
+            writeBuffer.Write(buf, off, len);
+        }
+
+        private void InternalFlush()
+        {
+            CheckNotDisposed();
+            if (!IsOpen)
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            byte[] buf = writeBuffer.GetBuffer();
+            int len = (int)writeBuffer.Length;
+            int data_len = len - HeaderSize;
+            if (data_len < 0)
+                throw new System.InvalidOperationException(); // logic error actually
+
+            // Inject message header into the reserved buffer space
+            EncodeFrameSize(data_len, buf);
+
+            // Send the entire message at once
+            transport.Write(buf, 0, len);
+
+            InitWriteBuffer();
+        }
+
+        public override void Flush()
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            transport.Flush();
+        }
+
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            CheckNotDisposed();
+            InternalFlush();
+
+            return transport.BeginFlush( callback, state);
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            transport.EndFlush( asyncResult);
+        }
+
+        private void InitWriteBuffer()
+        {
+            // Reserve space for message header to be put right before sending it out
+            writeBuffer.SetLength(HeaderSize);
+            writeBuffer.Seek(0, SeekOrigin.End);
+        }
+
+        private static void EncodeFrameSize(int frameSize, byte[] buf)
+        {
+            buf[0] = (byte)(0xff & (frameSize >> 24));
+            buf[1] = (byte)(0xff & (frameSize >> 16));
+            buf[2] = (byte)(0xff & (frameSize >> 8));
+            buf[3] = (byte)(0xff & (frameSize));
+        }
+
+        private static int DecodeFrameSize(byte[] buf)
+        {
+            return
+                ((buf[0] & 0xff) << 24) |
+                ((buf[1] & 0xff) << 16) |
+                ((buf[2] & 0xff) << 8) |
+                ((buf[3] & 0xff));
+        }
+
+
+        private void CheckNotDisposed()
+        {
+            if (_IsDisposed)
+                throw new ObjectDisposedException("TFramedTransport");
+        }
+
+        #region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (readBuffer != null)
+                        readBuffer.Dispose();
+                    if (writeBuffer != null)
+                        writeBuffer.Dispose();
+                    if (transport != null)
+                        transport.Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/THttpClient.cs b/lib/csharp/src/Transport/THttpClient.cs
new file mode 100644
index 0000000..986799c
--- /dev/null
+++ b/lib/csharp/src/Transport/THttpClient.cs
@@ -0,0 +1,486 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Threading;
+using System.Linq;
+using System.Security.Cryptography.X509Certificates;
+using System.IO.Compression;
+
+namespace Thrift.Transport
+{
+    public class THttpClient : TTransport, IDisposable
+    {
+        private readonly Uri uri;
+        private readonly X509Certificate[] certificates;
+        private Stream inputStream;
+        private MemoryStream outputStream = new MemoryStream();
+
+        // Timeouts in milliseconds
+        private int connectTimeout = 30000;
+
+        private int readTimeout = 30000;
+
+        private IDictionary<string, string> customHeaders = new Dictionary<string, string>();
+        private string userAgent = "C#/THttpClient";
+
+#if !SILVERLIGHT
+        private IWebProxy proxy = WebRequest.DefaultWebProxy;
+#endif
+
+        public THttpClient(Uri u)
+            : this(u, Enumerable.Empty<X509Certificate>())
+        {
+        }
+        public THttpClient(Uri u, string userAgent)
+            : this(u, userAgent, Enumerable.Empty<X509Certificate>())
+        {
+        }
+
+        public THttpClient(Uri u, IEnumerable<X509Certificate> certificates)
+        {
+            uri = u;
+            this.certificates = (certificates ?? Enumerable.Empty<X509Certificate>()).ToArray();
+        }
+        public THttpClient(Uri u, string userAgent, IEnumerable<X509Certificate> certificates)
+        {
+            uri = u;
+            this.userAgent = userAgent;
+            this.certificates = (certificates ?? Enumerable.Empty<X509Certificate>()).ToArray();
+        }
+
+        public int ConnectTimeout
+        {
+            set
+            {
+                connectTimeout = value;
+            }
+        }
+
+        public int ReadTimeout
+        {
+            set
+            {
+                readTimeout = value;
+            }
+        }
+
+        public IDictionary<string, string> CustomHeaders
+        {
+            get
+            {
+                return customHeaders;
+            }
+        }
+
+#if !SILVERLIGHT
+        public IWebProxy Proxy
+        {
+            set
+            {
+                proxy = value;
+            }
+        }
+#endif
+
+        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, "No request has been sent");
+            }
+
+            try
+            {
+                int ret = inputStream.Read(buf, off, len);
+
+                if (ret == -1)
+                {
+                    throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available");
+                }
+
+                return ret;
+            }
+            catch (IOException iox)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox);
+            }
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            outputStream.Write(buf, off, len);
+        }
+
+#if !SILVERLIGHT
+        public override void Flush()
+        {
+            try
+            {
+                SendRequest();
+            }
+            finally
+            {
+                outputStream = new MemoryStream();
+            }
+        }
+
+        private void SendRequest()
+        {
+            try
+            {
+                HttpWebRequest connection = CreateRequest();
+                connection.Headers.Add("Accept-Encoding", "gzip, deflate");
+
+                byte[] data = outputStream.ToArray();
+                connection.ContentLength = data.Length;
+
+                using (Stream requestStream = connection.GetRequestStream())
+                {
+                    requestStream.Write(data, 0, data.Length);
+
+                    // Resolve HTTP hang that can happens after successive calls by making sure
+                    // that we release the response and response stream. To support this, we copy
+                    // the response to a memory stream.
+                    using (var response = connection.GetResponse())
+                    {
+                        using (var responseStream = response.GetResponseStream())
+                        {
+                            // Copy the response to a memory stream so that we can
+                            // cleanly close the response and response stream.
+                            inputStream = new MemoryStream();
+                            byte[] buffer = new byte[8192];  // multiple of 4096
+                            int bytesRead;
+                            while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0)
+                            {
+                                inputStream.Write(buffer, 0, bytesRead);
+                            }
+                            inputStream.Seek(0, 0);
+                        }
+
+                        var encodings = response.Headers.GetValues("Content-Encoding");
+                        if (encodings != null)
+                        {
+                            foreach (var encoding in encodings)
+                            {
+                                switch (encoding)
+                                {
+                                    case "gzip":
+                                        DecompressGZipped(ref inputStream);
+                                        break;
+                                    case "deflate":
+                                        DecompressDeflated(ref inputStream);
+                                        break;
+                                    default:
+                                        break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            catch (IOException iox)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox);
+            }
+            catch (WebException wx)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx, wx);
+            }
+        }
+
+        private void DecompressDeflated(ref Stream inputStream)
+        {
+            var tmp = new MemoryStream();
+            using (var decomp = new DeflateStream(inputStream, CompressionMode.Decompress))
+            {
+                decomp.CopyTo(tmp);
+            }
+            inputStream.Dispose();
+            inputStream = tmp;
+            inputStream.Seek(0, 0);
+        }
+
+        private void DecompressGZipped(ref Stream inputStream)
+        {
+            var tmp = new MemoryStream();
+            using (var decomp = new GZipStream(inputStream, CompressionMode.Decompress))
+            {
+                decomp.CopyTo(tmp);
+            }
+            inputStream.Dispose();
+            inputStream = tmp;
+            inputStream.Seek(0, 0);
+        }
+#endif
+        private HttpWebRequest CreateRequest()
+        {
+            HttpWebRequest connection = (HttpWebRequest)WebRequest.Create(uri);
+
+
+#if !SILVERLIGHT
+            // Adding certificates through code is not supported with WP7 Silverlight
+            // see "Windows Phone 7 and Certificates_FINAL_121610.pdf"
+            connection.ClientCertificates.AddRange(certificates);
+
+            if (connectTimeout > 0)
+            {
+                connection.Timeout = connectTimeout;
+            }
+            if (readTimeout > 0)
+            {
+                connection.ReadWriteTimeout = readTimeout;
+            }
+#endif
+            // Make the request
+            connection.ContentType = "application/x-thrift";
+            connection.Accept = "application/x-thrift";
+            connection.UserAgent = userAgent;
+            connection.Method = "POST";
+#if !SILVERLIGHT
+            connection.ProtocolVersion = HttpVersion.Version10;
+#endif
+
+            //add custom headers here
+            foreach (KeyValuePair<string, string> item in customHeaders)
+            {
+#if !SILVERLIGHT
+                connection.Headers.Add(item.Key, item.Value);
+#else
+                connection.Headers[item.Key] = item.Value;
+#endif
+            }
+
+#if !SILVERLIGHT
+            connection.Proxy = proxy;
+#endif
+
+            return connection;
+        }
+
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            // Extract request and reset buffer
+            var data = outputStream.ToArray();
+
+            //requestBuffer_ = new MemoryStream();
+
+            try
+            {
+                // Create connection object
+                var flushAsyncResult = new FlushAsyncResult(callback, state);
+                flushAsyncResult.Connection = CreateRequest();
+
+                flushAsyncResult.Data = data;
+
+
+                flushAsyncResult.Connection.BeginGetRequestStream(GetRequestStreamCallback, flushAsyncResult);
+                return flushAsyncResult;
+
+            }
+            catch (IOException iox)
+            {
+                throw new TTransportException(iox.ToString(), iox);
+            }
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            try
+            {
+                var flushAsyncResult = (FlushAsyncResult)asyncResult;
+
+                if (!flushAsyncResult.IsCompleted)
+                {
+                    var waitHandle = flushAsyncResult.AsyncWaitHandle;
+                    waitHandle.WaitOne();  // blocking INFINITEly
+                    waitHandle.Close();
+                }
+
+                if (flushAsyncResult.AsyncException != null)
+                {
+                    throw flushAsyncResult.AsyncException;
+                }
+            }
+            finally
+            {
+                outputStream = new MemoryStream();
+            }
+
+        }
+
+        private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
+        {
+            var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState;
+            try
+            {
+                var reqStream = flushAsyncResult.Connection.EndGetRequestStream(asynchronousResult);
+                reqStream.Write(flushAsyncResult.Data, 0, flushAsyncResult.Data.Length);
+                reqStream.Flush();
+                reqStream.Close();
+
+                // Start the asynchronous operation to get the response
+                flushAsyncResult.Connection.BeginGetResponse(GetResponseCallback, flushAsyncResult);
+            }
+            catch (Exception exception)
+            {
+                flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception);
+                flushAsyncResult.UpdateStatusToComplete();
+                flushAsyncResult.NotifyCallbackWhenAvailable();
+            }
+        }
+
+        private void GetResponseCallback(IAsyncResult asynchronousResult)
+        {
+            var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState;
+            try
+            {
+                inputStream = flushAsyncResult.Connection.EndGetResponse(asynchronousResult).GetResponseStream();
+            }
+            catch (Exception exception)
+            {
+                flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception);
+            }
+            flushAsyncResult.UpdateStatusToComplete();
+            flushAsyncResult.NotifyCallbackWhenAvailable();
+        }
+
+        // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx
+        class FlushAsyncResult : IAsyncResult
+        {
+            private volatile Boolean _isCompleted;
+            private ManualResetEvent _evt;
+            private readonly AsyncCallback _cbMethod;
+            private readonly object _state;
+
+            public FlushAsyncResult(AsyncCallback cbMethod, object state)
+            {
+                _cbMethod = cbMethod;
+                _state = state;
+            }
+
+            internal byte[] Data { get; set; }
+            internal HttpWebRequest Connection { get; set; }
+            internal TTransportException AsyncException { get; set; }
+
+            public object AsyncState
+            {
+                get { return _state; }
+            }
+            public WaitHandle AsyncWaitHandle
+            {
+                get { return GetEvtHandle(); }
+            }
+            public bool CompletedSynchronously
+            {
+                get { return false; }
+            }
+            public bool IsCompleted
+            {
+                get { return _isCompleted; }
+            }
+            private readonly object _locker = new object();
+            private ManualResetEvent GetEvtHandle()
+            {
+                lock (_locker)
+                {
+                    if (_evt == null)
+                    {
+                        _evt = new ManualResetEvent(false);
+                    }
+                    if (_isCompleted)
+                    {
+                        _evt.Set();
+                    }
+                }
+                return _evt;
+            }
+            internal void UpdateStatusToComplete()
+            {
+                _isCompleted = true; //1. set _iscompleted to true
+                lock (_locker)
+                {
+                    if (_evt != null)
+                    {
+                        _evt.Set(); //2. set the event, when it exists
+                    }
+                }
+            }
+
+            internal void NotifyCallbackWhenAvailable()
+            {
+                if (_cbMethod != null)
+                {
+                    _cbMethod(this);
+                }
+            }
+        }
+
+        #region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (inputStream != null)
+                        inputStream.Dispose();
+                    if (outputStream != null)
+                        outputStream.Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/THttpHandler.cs b/lib/csharp/src/Transport/THttpHandler.cs
new file mode 100644
index 0000000..4115ef9
--- /dev/null
+++ b/lib/csharp/src/Transport/THttpHandler.cs
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *
+ */
+
+using System;
+using System.Web;
+using System.Net;
+using System.IO;
+
+using Thrift.Protocol;
+
+namespace Thrift.Transport
+{
+    public class THttpHandler : IHttpHandler
+    {
+        protected TProcessor processor;
+
+        protected TProtocolFactory inputProtocolFactory;
+        protected TProtocolFactory outputProtocolFactory;
+
+        protected const string contentType = "application/x-thrift";
+        protected System.Text.Encoding encoding = System.Text.Encoding.UTF8;
+
+        public THttpHandler(TProcessor processor)
+            : this(processor, new TBinaryProtocol.Factory())
+        {
+
+        }
+
+        public THttpHandler(TProcessor processor, TProtocolFactory protocolFactory)
+            : this(processor, protocolFactory, protocolFactory)
+        {
+
+        }
+
+        public THttpHandler(TProcessor processor, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory)
+        {
+            this.processor = processor;
+            this.inputProtocolFactory = inputProtocolFactory;
+            this.outputProtocolFactory = outputProtocolFactory;
+        }
+
+        public void ProcessRequest(HttpListenerContext context)
+        {
+            context.Response.ContentType = contentType;
+            context.Response.ContentEncoding = encoding;
+            ProcessRequest(context.Request.InputStream, context.Response.OutputStream);
+        }
+
+        public void ProcessRequest(HttpContext context)
+        {
+            context.Response.ContentType = contentType;
+            context.Response.ContentEncoding = encoding;
+            ProcessRequest(context.Request.InputStream, context.Response.OutputStream);
+        }
+
+        public void ProcessRequest(Stream input, Stream output)
+        {
+            TTransport transport = new TStreamTransport(input,output);
+
+            try
+            {
+                var inputProtocol = inputProtocolFactory.GetProtocol(transport);
+                var outputProtocol = outputProtocolFactory.GetProtocol(transport);
+
+                while (processor.Process(inputProtocol, outputProtocol))
+                {
+                }
+            }
+            catch (TTransportException)
+            {
+                // Client died, just move on
+            }
+            finally
+            {
+                transport.Close();
+            }
+        }
+
+        public bool IsReusable
+        {
+            get { return true; }
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs b/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs
new file mode 100644
index 0000000..e491f32
--- /dev/null
+++ b/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System.Threading.Tasks;
+using System.Web;
+using Thrift.Protocol;
+
+namespace Thrift.Transport
+{
+    /// <summary>
+    /// An async task based HTTP handler for processing thrift services.
+    /// </summary>
+    public class THttpTaskAsyncHandler : HttpTaskAsyncHandler
+    {
+        private readonly TAsyncProcessor _processor;
+        private readonly TProtocolFactory _inputProtocolFactory;
+        private readonly TProtocolFactory _outputProtocolFactory;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class
+        /// using the <see cref="TBinaryProtocol.Factory"/> for both input and output streams.
+        /// </summary>
+        /// <param name="processor">The async processor implementation.</param>
+        public THttpTaskAsyncHandler(TAsyncProcessor processor)
+            : this(processor, new TBinaryProtocol.Factory())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class
+        /// using <paramref name="protocolFactory"/> for both input and output streams.
+        /// </summary>
+        /// <param name="processor">The async processor implementation.</param>
+        /// <param name="protocolFactory">The protocol factory.</param>
+        public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory protocolFactory)
+            : this(processor, protocolFactory, protocolFactory)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="THttpTaskAsyncHandler"/> class.
+        /// </summary>
+        /// <param name="processor">The async processor implementation.</param>
+        /// <param name="inputProtocolFactory">The input protocol factory.</param>
+        /// <param name="outputProtocolFactory">The output protocol factory.</param>
+        public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory inputProtocolFactory,
+            TProtocolFactory outputProtocolFactory)
+        {
+            _processor = processor;
+            _inputProtocolFactory = inputProtocolFactory;
+            _outputProtocolFactory = outputProtocolFactory;
+        }
+
+        public override async Task ProcessRequestAsync(HttpContext context)
+        {
+            var transport = new TStreamTransport(context.Request.InputStream, context.Response.OutputStream);
+
+            try
+            {
+                var input = _inputProtocolFactory.GetProtocol(transport);
+                var output = _outputProtocolFactory.GetProtocol(transport);
+
+                while (await _processor.ProcessAsync(input, output))
+                {
+                }
+            }
+            catch (TTransportException)
+            {
+                // Client died, just move on
+            }
+            finally
+            {
+                transport.Close();
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TMemoryBuffer.cs b/lib/csharp/src/Transport/TMemoryBuffer.cs
new file mode 100644
index 0000000..303d083
--- /dev/null
+++ b/lib/csharp/src/Transport/TMemoryBuffer.cs
@@ -0,0 +1,117 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.IO;
+using System.Reflection;
+using Thrift.Protocol;
+
+namespace Thrift.Transport
+{
+    public class TMemoryBuffer : TTransport
+    {
+
+        private readonly MemoryStream byteStream;
+
+        public TMemoryBuffer()
+        {
+            byteStream = new MemoryStream();
+        }
+
+        public TMemoryBuffer(byte[] buf)
+        {
+            byteStream = new MemoryStream(buf);
+        }
+
+        public override void Open()
+        {
+            /** do nothing **/
+        }
+
+        public override void Close()
+        {
+            /** do nothing **/
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            return byteStream.Read(buf, off, len);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            byteStream.Write(buf, off, len);
+        }
+
+        public byte[] GetBuffer()
+        {
+            return byteStream.ToArray();
+        }
+
+
+        public override bool IsOpen
+        {
+            get { return true; }
+        }
+
+        public static byte[] Serialize(TAbstractBase s)
+        {
+            var t = new TMemoryBuffer();
+            var p = new TBinaryProtocol(t);
+
+            s.Write(p);
+
+            return t.GetBuffer();
+        }
+
+        public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase
+        {
+            var trans = new TMemoryBuffer(buf);
+            var p = new TBinaryProtocol(trans);
+            if (typeof(TBase).IsAssignableFrom(typeof(T)))
+            {
+                var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
+                var t = Activator.CreateInstance<T>();
+                method.Invoke(t, new object[] { p });
+                return t;
+            }
+            else
+            {
+                var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
+                return (T)method.Invoke(null, new object[] { p });
+            }
+        }
+
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (byteStream != null)
+                        byteStream.Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TNamedPipeClientTransport.cs b/lib/csharp/src/Transport/TNamedPipeClientTransport.cs
new file mode 100644
index 0000000..49a50aa
--- /dev/null
+++ b/lib/csharp/src/Transport/TNamedPipeClientTransport.cs
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.IO.Pipes;
+using System.Threading;
+
+namespace Thrift.Transport
+{
+    public class TNamedPipeClientTransport : TTransport
+    {
+        private NamedPipeClientStream client;
+        private string ServerName;
+        private string PipeName;
+        private int ConnectTimeout;
+
+        public TNamedPipeClientTransport(string pipe, int timeout = Timeout.Infinite)
+        {
+            ServerName = ".";
+            PipeName = pipe;
+            ConnectTimeout = timeout;
+        }
+
+        public TNamedPipeClientTransport(string server, string pipe, int timeout = Timeout.Infinite)
+        {
+            ServerName = (server != "") ? server : ".";
+            PipeName = pipe;
+            ConnectTimeout = timeout;
+        }
+
+        public override bool IsOpen
+        {
+            get { return client != null && client.IsConnected; }
+        }
+
+        public override void Open()
+        {
+            if (IsOpen)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen);
+            }
+            client = new NamedPipeClientStream(ServerName, PipeName, PipeDirection.InOut, PipeOptions.None);
+            client.Connect(ConnectTimeout);
+        }
+
+        public override void Close()
+        {
+            if (client != null)
+            {
+                client.Close();
+                client = null;
+            }
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            if (client == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            }
+
+            return client.Read(buf, off, len);
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            if (client == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+            }
+
+            // if necessary, send the data in chunks
+            // there's a system limit around 0x10000 bytes that we hit otherwise
+            // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section."
+            var nBytes = Math.Min(len, 15 * 4096);  // 16 would exceed the limit
+            while (nBytes > 0)
+            {
+                client.Write(buf, off, nBytes);
+
+                off += nBytes;
+                len -= nBytes;
+                nBytes = Math.Min(len, nBytes);
+            }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            client.Dispose();
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TNamedPipeServerTransport.cs b/lib/csharp/src/Transport/TNamedPipeServerTransport.cs
new file mode 100644
index 0000000..32215cf
--- /dev/null
+++ b/lib/csharp/src/Transport/TNamedPipeServerTransport.cs
@@ -0,0 +1,296 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.IO.Pipes;
+using System.Threading;
+using System.Security.Principal;
+
+namespace Thrift.Transport
+{
+    public class TNamedPipeServerTransport : TServerTransport
+    {
+        /// <summary>
+        /// This is the address of the Pipe on the localhost.
+        /// </summary>
+        private readonly string pipeAddress;
+        private NamedPipeServerStream stream = null;
+        private bool asyncMode = true;
+
+        public TNamedPipeServerTransport(string pipeAddress)
+        {
+            this.pipeAddress = pipeAddress;
+        }
+
+        public override void Listen()
+        {
+            // nothing to do here
+        }
+
+        public override void Close()
+        {
+            if (stream != null)
+            {
+                try
+                {
+                    stream.Close();
+                    stream.Dispose();
+                }
+                finally
+                {
+                    stream = null;
+                }
+            }
+        }
+
+        private void EnsurePipeInstance()
+        {
+            if (stream == null)
+            {
+                var direction = PipeDirection.InOut;
+                var maxconn = NamedPipeServerStream.MaxAllowedServerInstances;
+                var mode = PipeTransmissionMode.Byte;
+                var options = asyncMode ? PipeOptions.Asynchronous : PipeOptions.None;
+                const int INBUF_SIZE = 4096;
+                const int OUTBUF_SIZE = 4096;
+
+                // security
+                var security = new PipeSecurity();
+                security.AddAccessRule(
+                    new PipeAccessRule(
+                        new SecurityIdentifier(WellKnownSidType.WorldSid, null),
+                        PipeAccessRights.Read | PipeAccessRights.Write | PipeAccessRights.Synchronize | PipeAccessRights.CreateNewInstance,
+                        System.Security.AccessControl.AccessControlType.Allow
+                    )
+                );
+
+                try
+                {
+                    stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security);
+                }
+                catch (NotImplementedException)  // Mono still does not support async, fallback to sync
+                {
+                    if (asyncMode)
+                    {
+                        options &= (~PipeOptions.Asynchronous);
+                        stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security);
+                        asyncMode = false;
+                    }
+                    else
+                    {
+                        throw;
+                    }
+                }
+
+            }
+        }
+
+        protected override TTransport AcceptImpl()
+        {
+            try
+            {
+                EnsurePipeInstance();
+
+                if (asyncMode)
+                {
+                    var evt = new ManualResetEvent(false);
+                    Exception eOuter = null;
+
+                    stream.BeginWaitForConnection(asyncResult =>
+                    {
+                        try
+                        {
+                            if (stream != null)
+                                stream.EndWaitForConnection(asyncResult);
+                            else
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted);
+                        }
+                        catch (Exception e)
+                        {
+                            if (stream != null)
+                                eOuter = e;
+                            else
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
+                        }
+                        evt.Set();
+                    }, null);
+
+                    evt.WaitOne();
+
+                    if (eOuter != null)
+                        throw eOuter; // rethrow exception
+                }
+                else
+                {
+                    stream.WaitForConnection();
+                }
+
+                var trans = new ServerTransport(stream,asyncMode);
+                stream = null;  // pass ownership to ServerTransport
+                return trans;
+            }
+            catch (TTransportException)
+            {
+                Close();
+                throw;
+            }
+            catch (Exception e)
+            {
+                Close();
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message, e);
+            }
+        }
+
+        private class ServerTransport : TTransport
+        {
+            private NamedPipeServerStream stream;
+            private bool asyncMode;
+
+            public ServerTransport(NamedPipeServerStream stream, bool asyncMode)
+            {
+                this.stream = stream;
+                this.asyncMode = asyncMode;
+            }
+
+            public override bool IsOpen
+            {
+                get { return stream != null && stream.IsConnected; }
+            }
+
+            public override void Open()
+            {
+            }
+
+            public override void Close()
+            {
+                if (stream != null)
+                    stream.Close();
+            }
+
+            public override int Read(byte[] buf, int off, int len)
+            {
+                if (stream == null)
+                {
+                    throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+                }
+
+                if (asyncMode)
+                {
+                    Exception eOuter = null;
+                    var evt = new ManualResetEvent(false);
+                    int retval = 0;
+
+                    stream.BeginRead(buf, off, len, asyncResult =>
+                    {
+                        try
+                        {
+                            if (stream != null)
+                                retval = stream.EndRead(asyncResult);
+                            else
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted);
+                        }
+                        catch (Exception e)
+                        {
+                            if (stream != null)
+                                eOuter = e;
+                            else
+                                eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
+                        }
+                        evt.Set();
+                    }, null);
+
+                    evt.WaitOne();
+
+                    if (eOuter != null)
+                        throw eOuter; // rethrow exception
+                    else
+                        return retval;
+                }
+                else
+                {
+                    return stream.Read(buf, off, len);
+                }
+            }
+
+            public override void Write(byte[] buf, int off, int len)
+            {
+                if (stream == null)
+                {
+                    throw new TTransportException(TTransportException.ExceptionType.NotOpen);
+                }
+
+                // if necessary, send the data in chunks
+                // there's a system limit around 0x10000 bytes that we hit otherwise
+                // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section."
+                var nBytes = Math.Min(len, 15 * 4096);  // 16 would exceed the limit
+                while (nBytes > 0)
+                {
+
+                    if (asyncMode)
+                    {
+                        Exception eOuter = null;
+                        var evt = new ManualResetEvent(false);
+
+                        stream.BeginWrite(buf, off, nBytes, asyncResult =>
+                        {
+                            try
+                            {
+                                if (stream != null)
+                                    stream.EndWrite(asyncResult);
+                                else
+                                    eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted);
+                            }
+                            catch (Exception e)
+                            {
+                                if (stream != null)
+                                    eOuter = e;
+                                else
+                                    eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e);
+                            }
+                            evt.Set();
+                        }, null);
+
+                        evt.WaitOne();
+
+                        if (eOuter != null)
+                            throw eOuter; // rethrow exception
+                    }
+                    else
+                    {
+                        stream.Write(buf, off, nBytes);
+                    }
+
+                    off += nBytes;
+                    len -= nBytes;
+                    nBytes = Math.Min(len, nBytes);
+                }
+            }
+
+            protected override void Dispose(bool disposing)
+            {
+                if (stream != null)
+                    stream.Dispose();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/csharp/src/Transport/TServerSocket.cs b/lib/csharp/src/Transport/TServerSocket.cs
new file mode 100644
index 0000000..d8ec62a
--- /dev/null
+++ b/lib/csharp/src/Transport/TServerSocket.cs
@@ -0,0 +1,176 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Net.Sockets;
+
+
+namespace Thrift.Transport
+{
+    public class TServerSocket : TServerTransport
+    {
+        /// <summary>
+        /// Underlying server with socket.
+        /// </summary>
+        private TcpListener server = null;
+
+        /// <summary>
+        /// Port to listen on.
+        /// </summary>
+        private int port = 0;
+
+        /// <summary>
+        /// Timeout for client sockets from accept.
+        /// </summary>
+        private int clientTimeout = 0;
+
+        /// <summary>
+        /// Whether or not to wrap new TSocket connections in buffers.
+        /// </summary>
+        private bool useBufferedSockets = false;
+
+        /// <summary>
+        /// Creates a server socket from underlying socket object.
+        /// </summary>
+        public TServerSocket(TcpListener listener)
+            : this(listener, 0)
+        {
+        }
+
+        /// <summary>
+        /// Creates a server socket from underlying socket object.
+        /// </summary>
+        public TServerSocket(TcpListener listener, int clientTimeout)
+        {
+            this.server = listener;
+            this.clientTimeout = clientTimeout;
+        }
+
+        /// <summary>
+        /// Creates just a port listening server socket.
+        /// </summary>
+        public TServerSocket(int port)
+            : this(port, 0)
+        {
+        }
+
+        /// <summary>
+        /// Creates just a port listening server socket.
+        /// </summary>
+        public TServerSocket(int port, int clientTimeout)
+            : this(port, clientTimeout, false)
+        {
+        }
+
+        public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
+        {
+            this.port = port;
+            this.clientTimeout = clientTimeout;
+            this.useBufferedSockets = useBufferedSockets;
+            try
+            {
+                // Make server socket
+                this.server = TSocketVersionizer.CreateTcpListener(this.port);
+                this.server.Server.NoDelay = true;
+            }
+            catch (Exception ex)
+            {
+                server = null;
+                throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex);
+            }
+        }
+
+        public override void Listen()
+        {
+            // Make sure not to block on accept
+            if (server != null)
+            {
+                try
+                {
+                    server.Start();
+                }
+                catch (SocketException sx)
+                {
+                    throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx);
+                }
+            }
+        }
+
+        protected override TTransport AcceptImpl()
+        {
+            if (server == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
+            }
+            try
+            {
+                TSocket result2 = null;
+                TcpClient result = server.AcceptTcpClient();
+                try
+                {
+                    result2 = new TSocket(result);
+                    result2.Timeout = clientTimeout;
+                    if (useBufferedSockets)
+                    {
+                        TBufferedTransport result3 = new TBufferedTransport(result2);
+                        return result3;
+                    }
+                    else
+                    {
+                        return result2;
+                    }
+                }
+                catch (System.Exception)
+                {
+                    // If a TSocket was successfully created, then let
+                    // it do proper cleanup of the TcpClient object.
+                    if (result2 != null)
+                        result2.Dispose();
+                    else //  Otherwise, clean it up ourselves.
+                        ((IDisposable)result).Dispose();
+                    throw;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new TTransportException(ex.ToString(), ex);
+            }
+        }
+
+        public override void Close()
+        {
+            if (server != null)
+            {
+                try
+                {
+                    server.Stop();
+                }
+                catch (Exception ex)
+                {
+                    throw new TTransportException("WARNING: Could not close server socket: " + ex, 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..e63880b
--- /dev/null
+++ b/lib/csharp/src/Transport/TServerTransport.cs
@@ -0,0 +1,44 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+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/TSilverlightSocket.cs b/lib/csharp/src/Transport/TSilverlightSocket.cs
new file mode 100644
index 0000000..40469ab
--- /dev/null
+++ b/lib/csharp/src/Transport/TSilverlightSocket.cs
@@ -0,0 +1,393 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+/* only for silverlight */
+#if SILVERLIGHT
+
+using System;
+using System.Net.Sockets;
+using System.IO;
+using System.Net;
+using System.Threading;
+
+namespace Thrift.Transport
+{
+    public class TSilverlightSocket : TTransport
+    {
+        Socket socket = null;
+        static ManualResetEvent readAsyncComplete = new ManualResetEvent(false);
+        public event EventHandler<SocketAsyncEventArgs> connectHandler = null;
+
+        // memory stream for write cache.
+        private MemoryStream outputStream = new MemoryStream();
+
+        private string host = null;
+        private int port = 0;
+        private int timeout = 0;
+
+        // constructor
+        public TSilverlightSocket(string host, int port)
+            : this(host, port, 0)
+        {
+        }
+
+        // constructor
+        public TSilverlightSocket(string host, int port, int timeout)
+        {
+            this.host = host;
+            this.port = port;
+            this.timeout = timeout;
+
+            InitSocket();
+        }
+
+        private void InitSocket()
+        {
+            // Create a stream-based, TCP socket using the InterNetwork Address Family.
+            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+            socket.NoDelay = true;
+        }
+
+        public int Timeout
+        {
+            set
+            {
+                timeout = value;
+            }
+        }
+
+        public string Host
+        {
+            get
+            {
+                return host;
+            }
+        }
+
+        public int Port
+        {
+            get
+            {
+                return port;
+            }
+        }
+
+        public override bool IsOpen
+        {
+            get
+            {
+                if (socket == null)
+                {
+                    return false;
+                }
+
+                return socket.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 (socket == null)
+            {
+                InitSocket();
+            }
+
+            if (timeout == 0)     // no timeout -> infinite
+            {
+                timeout = 10000;  // set a default timeout for WP.
+            }
+
+            {
+                // Create DnsEndPoint. The hostName and port are passed in to this method.
+                DnsEndPoint hostEntry = new DnsEndPoint(this.host, this.port);
+
+                // Create a SocketAsyncEventArgs object to be used in the connection request
+                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
+                socketEventArg.RemoteEndPoint = hostEntry;
+
+                // Inline event handler for the Completed event.
+                // Note: This event handler was implemented inline in order to make this method self-contained.
+                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
+                {
+                    if (connectHandler != null)
+                    {
+                        connectHandler(this, e);
+                    }
+                });
+
+                // Make an asynchronous Connect request over the socket
+                socket.ConnectAsync(socketEventArg);
+            }
+        }
+
+        public override int Read(byte[] buf, int off, int len)
+        {
+            bool _timeout = true;
+            string _error = null;
+            int _recvBytes = -1;
+
+            if (socket == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Socket is not open");
+            }
+
+            // Create SocketAsyncEventArgs context object
+            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
+            socketEventArg.RemoteEndPoint = socket.RemoteEndPoint;
+
+            // Setup the buffer to receive the data
+            socketEventArg.SetBuffer(buf, off, len);
+
+            // Inline event handler for the Completed event.
+            // Note: This even handler was implemented inline in order to make
+            // this method self-contained.
+            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
+            {
+                _timeout = false;
+
+                if (e.SocketError == SocketError.Success)
+                {
+                    _recvBytes = e.BytesTransferred;
+                }
+                else
+                {
+                    _error = e.SocketError.ToString();
+                }
+
+                readAsyncComplete.Set();
+            });
+
+            // Sets the state of the event to nonsignaled, causing threads to block
+            readAsyncComplete.Reset();
+
+            // Make an asynchronous Receive request over the socket
+            socket.ReceiveAsync(socketEventArg);
+
+            // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
+            // If no response comes back within this time then proceed
+            readAsyncComplete.WaitOne(this.timeout);
+
+            if (_timeout)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Socket recv timeout");
+            }
+
+            if (_error != null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, _error);
+            }
+
+            return _recvBytes;
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            outputStream.Write(buf, off, len);
+        }
+
+        private void beginFlush_Completed(object sender, SocketAsyncEventArgs e)
+        {
+            FlushAsyncResult flushAsyncResult = e.UserToken as FlushAsyncResult;
+            flushAsyncResult.UpdateStatusToComplete();
+            flushAsyncResult.NotifyCallbackWhenAvailable();
+
+            if (e.SocketError != SocketError.Success)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, e.SocketError.ToString());
+            }
+        }
+
+        public override IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            // Extract request and reset buffer
+            byte[] data = outputStream.ToArray();
+
+            FlushAsyncResult flushAsyncResult = new FlushAsyncResult(callback, state);
+
+            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
+            socketEventArg.RemoteEndPoint = socket.RemoteEndPoint;
+            socketEventArg.UserToken = flushAsyncResult;
+
+            socketEventArg.Completed += beginFlush_Completed;
+            socketEventArg.SetBuffer(data, 0, data.Length);
+
+            socket.SendAsync(socketEventArg);
+
+            return flushAsyncResult;
+        }
+
+        public override void EndFlush(IAsyncResult asyncResult)
+        {
+            try
+            {
+                var flushAsyncResult = (FlushAsyncResult)asyncResult;
+
+                if (!flushAsyncResult.IsCompleted)
+                {
+                    var waitHandle = flushAsyncResult.AsyncWaitHandle;
+                    waitHandle.WaitOne();
+                    waitHandle.Close();
+                }
+
+                if (flushAsyncResult.AsyncException != null)
+                {
+                    throw flushAsyncResult.AsyncException;
+                }
+            }
+            finally
+            {
+                outputStream = new MemoryStream();
+            }
+        }
+
+        // Copy from impl from THttpClient.cs
+        // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx
+        class FlushAsyncResult : IAsyncResult
+        {
+            private volatile Boolean _isCompleted;
+            private ManualResetEvent _evt;
+            private readonly AsyncCallback _cbMethod;
+            private readonly object _state;
+
+            public FlushAsyncResult(AsyncCallback cbMethod, object state)
+            {
+                _cbMethod = cbMethod;
+                _state = state;
+            }
+
+            internal byte[] Data { get; set; }
+            internal Socket Connection { get; set; }
+            internal TTransportException AsyncException { get; set; }
+
+            public object AsyncState
+            {
+                get { return _state; }
+            }
+
+            public WaitHandle AsyncWaitHandle
+            {
+                get { return GetEvtHandle(); }
+            }
+
+            public bool CompletedSynchronously
+            {
+                get { return false; }
+            }
+
+            public bool IsCompleted
+            {
+                get { return _isCompleted; }
+            }
+
+            private readonly object _locker = new object();
+
+            private ManualResetEvent GetEvtHandle()
+            {
+                lock (_locker)
+                {
+                    if (_evt == null)
+                    {
+                        _evt = new ManualResetEvent(false);
+                    }
+                    if (_isCompleted)
+                    {
+                        _evt.Set();
+                    }
+                }
+                return _evt;
+            }
+
+            internal void UpdateStatusToComplete()
+            {
+                _isCompleted = true; //1. set _iscompleted to true
+                lock (_locker)
+                {
+                    if (_evt != null)
+                    {
+                        _evt.Set(); //2. set the event, when it exists
+                    }
+                }
+            }
+
+            internal void NotifyCallbackWhenAvailable()
+            {
+                if (_cbMethod != null)
+                {
+                    _cbMethod(this);
+                }
+            }
+        }
+
+        public override void Close()
+        {
+            if (socket != null)
+            {
+                socket.Close();
+                socket = null;
+            }
+        }
+
+#region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (outputStream != null)
+                    {
+                        outputStream.Dispose();
+                    }
+                    outputStream = null;
+                    if (socket != null)
+                    {
+                        ((IDisposable)socket).Dispose();
+                    }
+                }
+            }
+            _IsDisposed = true;
+        }
+#endregion
+    }
+}
+
+
+#endif
diff --git a/lib/csharp/src/Transport/TSocket.cs b/lib/csharp/src/Transport/TSocket.cs
new file mode 100644
index 0000000..d8fa335
--- /dev/null
+++ b/lib/csharp/src/Transport/TSocket.cs
@@ -0,0 +1,245 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+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()
+        {
+            this.client = TSocketVersionizer.CreateTcpClient();
+            this.client.ReceiveTimeout = client.SendTimeout = timeout;
+            this.client.Client.NoDelay = true;
+        }
+
+        public int Timeout
+        {
+            set
+            {
+                client.ReceiveTimeout = client.SendTimeout = timeout = value;
+            }
+        }
+
+        public TcpClient TcpClient
+        {
+            get
+            {
+                return client;
+            }
+        }
+
+        public string Host
+        {
+            get
+            {
+                return host;
+            }
+        }
+
+        public int Port
+        {
+            get
+            {
+                return port;
+            }
+        }
+
+        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();
+            }
+
+            if (timeout == 0)            // no timeout -> infinite
+            {
+                client.Connect(host, port);
+            }
+            else                        // we have a timeout -> use it
+            {
+                ConnectHelper hlp = new ConnectHelper(client);
+                IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
+                bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
+                if (!bConnected)
+                {
+                    lock (hlp.Mutex)
+                    {
+                        if (hlp.CallbackDone)
+                        {
+                            asyncres.AsyncWaitHandle.Close();
+                            client.Close();
+                        }
+                        else
+                        {
+                            hlp.DoCleanup = true;
+                            client = null;
+                        }
+                    }
+                    throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
+                }
+            }
+
+            inputStream = client.GetStream();
+            outputStream = client.GetStream();
+        }
+
+
+        static void ConnectCallback(IAsyncResult asyncres)
+        {
+            ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
+            lock (hlp.Mutex)
+            {
+                hlp.CallbackDone = true;
+
+                try
+                {
+                    if (hlp.Client.Client != null)
+                        hlp.Client.EndConnect(asyncres);
+                }
+                catch (Exception)
+                {
+                    // catch that away
+                }
+
+                if (hlp.DoCleanup)
+                {
+                    try
+                    {
+                        asyncres.AsyncWaitHandle.Close();
+                    }
+                    catch (Exception) { }
+
+                    try
+                    {
+                        if (hlp.Client is IDisposable)
+                            ((IDisposable)hlp.Client).Dispose();
+                    }
+                    catch (Exception) { }
+                    hlp.Client = null;
+                }
+            }
+        }
+
+        private class ConnectHelper
+        {
+            public object Mutex = new object();
+            public bool DoCleanup = false;
+            public bool CallbackDone = false;
+            public TcpClient Client;
+            public ConnectHelper(TcpClient client)
+            {
+                Client = client;
+            }
+        }
+
+        public override void Close()
+        {
+            base.Close();
+            if (client != null)
+            {
+                client.Close();
+                client = null;
+            }
+        }
+
+        #region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (client != null)
+                        ((IDisposable)client).Dispose();
+                    base.Dispose(disposing);
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/TSocketVersionizer.cs b/lib/csharp/src/Transport/TSocketVersionizer.cs
new file mode 100644
index 0000000..8c2f8e9
--- /dev/null
+++ b/lib/csharp/src/Transport/TSocketVersionizer.cs
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text;
+#if NET45
+using System.Threading.Tasks;
+#endif
+
+namespace Thrift.Transport
+{
+    /// <summary>
+    /// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
+    /// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
+    /// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
+    /// </summary>
+    internal static class TSocketVersionizer
+    {
+        /// <summary>
+        /// Creates a TcpClient according to the capabilities of the used framework.
+        /// </summary>
+        internal static TcpClient CreateTcpClient()
+        {
+            TcpClient client = null;
+
+#if NET45
+            client = new TcpClient(AddressFamily.InterNetworkV6);
+            client.Client.DualMode = true;
+#else
+            client = new TcpClient(AddressFamily.InterNetwork);
+#endif
+
+            return client;
+        }
+
+        /// <summary>
+        /// Creates a TcpListener according to the capabilities of the used framework.
+        /// </summary>
+        internal static TcpListener CreateTcpListener(Int32 port)
+        {
+            TcpListener listener = null;
+
+#if NET45
+            listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
+            listener.Server.DualMode = true;
+#else
+
+            listener = new TcpListener(System.Net.IPAddress.Any, port);
+#endif
+
+            return listener;
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TStreamTransport.cs b/lib/csharp/src/Transport/TStreamTransport.cs
new file mode 100644
index 0000000..304599f
--- /dev/null
+++ b/lib/csharp/src/Transport/TStreamTransport.cs
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.IO;
+
+namespace Thrift.Transport
+{
+    public class TStreamTransport : TTransport
+    {
+        protected Stream inputStream;
+        protected Stream outputStream;
+
+        protected TStreamTransport()
+        {
+        }
+
+        public TStreamTransport(Stream inputStream, Stream outputStream)
+        {
+            this.inputStream = inputStream;
+            this.outputStream = outputStream;
+        }
+
+        public Stream OutputStream
+        {
+            get { return outputStream; }
+        }
+
+        public Stream InputStream
+        {
+            get { return inputStream; }
+        }
+
+        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();
+        }
+
+
+        #region " IDisposable Support "
+        private bool _IsDisposed;
+
+        // IDisposable
+        protected override void Dispose(bool disposing)
+        {
+            if (!_IsDisposed)
+            {
+                if (disposing)
+                {
+                    if (InputStream != null)
+                        InputStream.Dispose();
+                    if (OutputStream != null)
+                        OutputStream.Dispose();
+                }
+            }
+            _IsDisposed = true;
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/TTLSServerSocket.cs b/lib/csharp/src/Transport/TTLSServerSocket.cs
new file mode 100644
index 0000000..716a97c
--- /dev/null
+++ b/lib/csharp/src/Transport/TTLSServerSocket.cs
@@ -0,0 +1,223 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Thrift.Transport
+{
+    /// <summary>
+    /// SSL Server Socket Wrapper Class
+    /// </summary>
+    public class TTLSServerSocket : TServerTransport
+    {
+        /// <summary>
+        /// Underlying tcp server
+        /// </summary>
+        private TcpListener server = null;
+
+        /// <summary>
+        /// The port where the socket listen
+        /// </summary>
+        private int port = 0;
+
+        /// <summary>
+        /// Timeout for the created server socket
+        /// </summary>
+        private readonly int clientTimeout;
+
+        /// <summary>
+        /// Whether or not to wrap new TSocket connections in buffers
+        /// </summary>
+        private bool useBufferedSockets = false;
+
+        /// <summary>
+        /// The servercertificate with the private- and public-key
+        /// </summary>
+        private X509Certificate serverCertificate;
+
+        /// <summary>
+        /// The function to validate the client certificate.
+        /// </summary>
+        private RemoteCertificateValidationCallback clientCertValidator;
+
+        /// <summary>
+        /// The function to determine which certificate to use.
+        /// </summary>
+        private LocalCertificateSelectionCallback localCertificateSelectionCallback;
+
+        /// <summary>
+        /// The SslProtocols value that represents the protocol used for authentication.
+        /// </summary>
+        private readonly SslProtocols sslProtocols;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
+        /// </summary>
+        /// <param name="port">The port where the server runs.</param>
+        /// <param name="certificate">The certificate object.</param>
+        public TTLSServerSocket(int port, X509Certificate2 certificate)
+            : this(port, 0, certificate)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
+        /// </summary>
+        /// <param name="port">The port where the server runs.</param>
+        /// <param name="clientTimeout">Send/receive timeout.</param>
+        /// <param name="certificate">The certificate object.</param>
+        public TTLSServerSocket(int port, int clientTimeout, X509Certificate2 certificate)
+            : this(port, clientTimeout, false, certificate)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
+        /// </summary>
+        /// <param name="port">The port where the server runs.</param>
+        /// <param name="clientTimeout">Send/receive timeout.</param>
+        /// <param name="useBufferedSockets">If set to <c>true</c> [use buffered sockets].</param>
+        /// <param name="certificate">The certificate object.</param>
+        /// <param name="clientCertValidator">The certificate validator.</param>
+        /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param>
+        /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param>
+        public TTLSServerSocket(
+            int port,
+            int clientTimeout,
+            bool useBufferedSockets,
+            X509Certificate2 certificate,
+            RemoteCertificateValidationCallback clientCertValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+.
+            SslProtocols sslProtocols = SslProtocols.Tls)
+        {
+            if (!certificate.HasPrivateKey)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key");
+            }
+
+            this.port = port;
+            this.clientTimeout = clientTimeout;
+            this.serverCertificate = certificate;
+            this.useBufferedSockets = useBufferedSockets;
+            this.clientCertValidator = clientCertValidator;
+            this.localCertificateSelectionCallback = localCertificateSelectionCallback;
+            this.sslProtocols = sslProtocols;
+            try
+            {
+                // Create server socket
+                this.server = TSocketVersionizer.CreateTcpListener(this.port);
+                this.server.Server.NoDelay = true;
+            }
+            catch (Exception ex)
+            {
+                server = null;
+                throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex);
+            }
+        }
+
+        /// <summary>
+        /// Starts the server.
+        /// </summary>
+        public override void Listen()
+        {
+            // Make sure accept is not blocking
+            if (this.server != null)
+            {
+                try
+                {
+                    this.server.Start();
+                }
+                catch (SocketException sx)
+                {
+                    throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Callback for Accept Implementation
+        /// </summary>
+        /// <returns>
+        /// TTransport-object.
+        /// </returns>
+        protected override TTransport AcceptImpl()
+        {
+            if (this.server == null)
+            {
+                throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
+            }
+
+            try
+            {
+                TcpClient client = this.server.AcceptTcpClient();
+                client.SendTimeout = client.ReceiveTimeout = this.clientTimeout;
+
+                //wrap the client in an SSL Socket passing in the SSL cert
+                TTLSSocket socket = new TTLSSocket(
+                    client,
+                    this.serverCertificate,
+                    true,
+                    this.clientCertValidator,
+                    this.localCertificateSelectionCallback,
+                    this.sslProtocols);
+
+                socket.setupTLS();
+
+                if (useBufferedSockets)
+                {
+                    TBufferedTransport trans = new TBufferedTransport(socket);
+                    return trans;
+                }
+                else
+                {
+                    return socket;
+                }
+
+            }
+            catch (Exception ex)
+            {
+                throw new TTransportException(ex.ToString(), ex);
+            }
+        }
+
+        /// <summary>
+        /// Stops the Server
+        /// </summary>
+        public override void Close()
+        {
+            if (this.server != null)
+            {
+                try
+                {
+                    this.server.Stop();
+                }
+                catch (Exception ex)
+                {
+                    throw new TTransportException("WARNING: Could not close server socket: " + ex, ex);
+                }
+                this.server = null;
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TTLSSocket.cs b/lib/csharp/src/Transport/TTLSSocket.cs
new file mode 100644
index 0000000..06286dc
--- /dev/null
+++ b/lib/csharp/src/Transport/TTLSSocket.cs
@@ -0,0 +1,445 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+using System;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Thrift.Transport
+{
+    /// <summary>
+    /// SSL Socket Wrapper class
+    /// </summary>
+    public class TTLSSocket : TStreamTransport
+    {
+        /// <summary>
+        /// Internal TCP Client
+        /// </summary>
+        private TcpClient client;
+
+        /// <summary>
+        /// The host
+        /// </summary>
+        private string host;
+
+        /// <summary>
+        /// The port
+        /// </summary>
+        private int port;
+
+        /// <summary>
+        /// The timeout for the connection
+        /// </summary>
+        private int timeout;
+
+        /// <summary>
+        /// Internal SSL Stream for IO
+        /// </summary>
+        private SslStream secureStream;
+
+        /// <summary>
+        /// Defines wheter or not this socket is a server socket<br/>
+        /// This is used for the TLS-authentication
+        /// </summary>
+        private bool isServer;
+
+        /// <summary>
+        /// The certificate
+        /// </summary>
+        private X509Certificate certificate;
+
+        /// <summary>
+        /// User defined certificate validator.
+        /// </summary>
+        private RemoteCertificateValidationCallback certValidator;
+
+        /// <summary>
+        /// The function to determine which certificate to use.
+        /// </summary>
+        private LocalCertificateSelectionCallback localCertificateSelectionCallback;
+
+        /// <summary>
+        /// The SslProtocols value that represents the protocol used for authentication.SSL protocols to be used.
+        /// </summary>
+        private readonly SslProtocols sslProtocols;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSSocket"/> class.
+        /// </summary>
+        /// <param name="client">An already created TCP-client</param>
+        /// <param name="certificate">The certificate.</param>
+        /// <param name="isServer">if set to <c>true</c> [is server].</param>
+        /// <param name="certValidator">User defined cert validator.</param>
+        /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param>
+        /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param>
+        public TTLSSocket(
+            TcpClient client,
+            X509Certificate certificate,
+            bool isServer = false,
+            RemoteCertificateValidationCallback certValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+.
+            SslProtocols sslProtocols = SslProtocols.Tls)
+        {
+            this.client = client;
+            this.certificate = certificate;
+            this.certValidator = certValidator;
+            this.localCertificateSelectionCallback = localCertificateSelectionCallback;
+            this.sslProtocols = sslProtocols;
+            this.isServer = isServer;
+            if (isServer && certificate == null)
+            {
+                throw new ArgumentException("TTLSSocket needs certificate to be used for server", "certificate");
+            }
+
+            if (IsOpen)
+            {
+                base.inputStream = client.GetStream();
+                base.outputStream = client.GetStream();
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSSocket"/> class.
+        /// </summary>
+        /// <param name="host">The host, where the socket should connect to.</param>
+        /// <param name="port">The port.</param>
+        /// <param name="certificatePath">The certificate path.</param>
+        /// <param name="certValidator">User defined cert validator.</param>
+        /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param>
+        /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param>
+        public TTLSSocket(
+            string host,
+            int port,
+            string certificatePath,
+            RemoteCertificateValidationCallback certValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            SslProtocols sslProtocols = SslProtocols.Tls)
+            : this(host, port, 0, X509Certificate.CreateFromCertFile(certificatePath), certValidator, localCertificateSelectionCallback, sslProtocols)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSSocket"/> class.
+        /// </summary>
+        /// <param name="host">The host, where the socket should connect to.</param>
+        /// <param name="port">The port.</param>
+        /// <param name="certificate">The certificate.</param>
+        /// <param name="certValidator">User defined cert validator.</param>
+        /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param>
+        /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param>
+        public TTLSSocket(
+            string host,
+            int port,
+            X509Certificate certificate = null,
+            RemoteCertificateValidationCallback certValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            SslProtocols sslProtocols = SslProtocols.Tls)
+            : this(host, port, 0, certificate, certValidator, localCertificateSelectionCallback, sslProtocols)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="TTLSSocket"/> class.
+        /// </summary>
+        /// <param name="host">The host, where the socket should connect to.</param>
+        /// <param name="port">The port.</param>
+        /// <param name="timeout">The timeout.</param>
+        /// <param name="certificate">The certificate.</param>
+        /// <param name="certValidator">User defined cert validator.</param>
+        /// <param name="localCertificateSelectionCallback">The callback to select which certificate to use.</param>
+        /// <param name="sslProtocols">The SslProtocols value that represents the protocol used for authentication.</param>
+        public TTLSSocket(
+            string host,
+            int port,
+            int timeout,
+            X509Certificate certificate,
+            RemoteCertificateValidationCallback certValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            SslProtocols sslProtocols = SslProtocols.Tls)
+        {
+            this.host = host;
+            this.port = port;
+            this.timeout = timeout;
+            this.certificate = certificate;
+            this.certValidator = certValidator;
+            this.localCertificateSelectionCallback = localCertificateSelectionCallback;
+            this.sslProtocols = sslProtocols;
+
+            InitSocket();
+        }
+
+        /// <summary>
+        /// Creates the TcpClient and sets the timeouts
+        /// </summary>
+        private void InitSocket()
+        {
+            client = TSocketVersionizer.CreateTcpClient();
+            client.ReceiveTimeout = client.SendTimeout = timeout;
+            client.Client.NoDelay = true;
+        }
+
+        /// <summary>
+        /// Sets Send / Recv Timeout for IO
+        /// </summary>
+        public int Timeout
+        {
+            set
+            {
+                this.client.ReceiveTimeout = this.client.SendTimeout = this.timeout = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets the TCP client.
+        /// </summary>
+        public TcpClient TcpClient
+        {
+            get
+            {
+                return client;
+            }
+        }
+
+        /// <summary>
+        /// Gets the host.
+        /// </summary>
+        public string Host
+        {
+            get
+            {
+                return host;
+            }
+        }
+
+        /// <summary>
+        /// Gets the port.
+        /// </summary>
+        public int Port
+        {
+            get
+            {
+                return port;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether TCP Client is Cpen
+        /// </summary>
+        public override bool IsOpen
+        {
+            get
+            {
+                if (this.client == null)
+                {
+                    return false;
+                }
+
+                return this.client.Connected;
+            }
+        }
+
+        /// <summary>
+        /// Validates the certificates!<br/>
+        /// </summary>
+        /// <param name="sender">The sender-object.</param>
+        /// <param name="certificate">The used certificate.</param>
+        /// <param name="chain">The certificate chain.</param>
+        /// <param name="sslValidationErrors">An enum, which lists all the errors from the .NET certificate check.</param>
+        /// <returns></returns>
+        private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors)
+        {
+            return (sslValidationErrors == SslPolicyErrors.None);
+        }
+
+        /// <summary>
+        /// Connects to the host and starts the routine, which sets up the TLS
+        /// </summary>
+        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();
+            }
+
+            if (timeout == 0)            // no timeout -> infinite
+            {
+                client.Connect(host, port);
+            }
+            else                        // we have a timeout -> use it
+            {
+                ConnectHelper hlp = new ConnectHelper(client);
+                IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
+                bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
+                if (!bConnected)
+                {
+                    lock (hlp.Mutex)
+                    {
+                        if (hlp.CallbackDone)
+                        {
+                            asyncres.AsyncWaitHandle.Close();
+                            client.Close();
+                        }
+                        else
+                        {
+                            hlp.DoCleanup = true;
+                            client = null;
+                        }
+                    }
+                    throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
+                }
+            }
+
+            setupTLS();
+        }
+
+        /// <summary>
+        /// Creates a TLS-stream and lays it over the existing socket
+        /// </summary>
+        public void setupTLS()
+        {
+            RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator;
+
+            if (this.localCertificateSelectionCallback != null)
+            {
+                this.secureStream = new SslStream(
+                    this.client.GetStream(),
+                    false,
+                    validator,
+                    this.localCertificateSelectionCallback
+                );
+            }
+            else
+            {
+                this.secureStream = new SslStream(
+                    this.client.GetStream(),
+                    false,
+                    validator
+                );
+            }
+
+            try
+            {
+                if (isServer)
+                {
+                    // Server authentication
+                    this.secureStream.AuthenticateAsServer(this.certificate, this.certValidator != null, sslProtocols, true);
+                }
+                else
+                {
+                    // Client authentication
+                    X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
+                    this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true);
+                }
+            }
+            catch (Exception)
+            {
+                this.Close();
+                throw;
+            }
+
+            inputStream = this.secureStream;
+            outputStream = this.secureStream;
+        }
+        
+        static void ConnectCallback(IAsyncResult asyncres)
+        {
+            ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
+            lock (hlp.Mutex)
+            {
+                hlp.CallbackDone = true;
+
+                try
+                {
+                    if (hlp.Client.Client != null)
+                        hlp.Client.EndConnect(asyncres);
+                }
+                catch (Exception)
+                {
+                    // catch that away
+                }
+
+                if (hlp.DoCleanup)
+                {
+                    try
+                    {
+                        asyncres.AsyncWaitHandle.Close();
+                    }
+                    catch (Exception) { }
+
+                    try
+                    {
+                        if (hlp.Client is IDisposable)
+                            ((IDisposable)hlp.Client).Dispose();
+                    }
+                    catch (Exception) { }
+                    hlp.Client = null;
+                }
+            }
+        }
+
+        private class ConnectHelper
+        {
+            public object Mutex = new object();
+            public bool DoCleanup = false;
+            public bool CallbackDone = false;
+            public TcpClient Client;
+            public ConnectHelper(TcpClient client)
+            {
+                Client = client;
+            }
+        }
+
+        /// <summary>
+        /// Closes the SSL Socket
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+            if (this.client != null)
+            {
+                this.client.Close();
+                this.client = null;
+            }
+
+            if (this.secureStream != null)
+            {
+                this.secureStream.Close();
+                this.secureStream = null;
+            }
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TTransport.cs b/lib/csharp/src/Transport/TTransport.cs
new file mode 100644
index 0000000..5e4ac22
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransport.cs
@@ -0,0 +1,146 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+using System.IO;
+
+namespace Thrift.Transport
+{
+    public abstract class TTransport : IDisposable
+    {
+        public abstract bool IsOpen
+        {
+            get;
+        }
+
+        private byte[] _peekBuffer = new byte[1];
+        private bool _hasPeekByte;
+
+        public bool Peek()
+        {
+            //If we already have a byte read but not consumed, do nothing.
+            if (_hasPeekByte)
+                return true;
+
+            //If transport closed we can't peek.
+            if (!IsOpen)
+                return false;
+
+            //Try to read one byte. If succeeds we will need to store it for the next read.
+            try
+            {
+                int bytes = Read(_peekBuffer, 0, 1);
+                if (bytes == 0)
+                    return false;
+            }
+            catch (IOException)
+            {
+                return false;
+            }
+
+            _hasPeekByte = true;
+            return true;
+        }
+
+        public abstract void Open();
+
+        public abstract void Close();
+
+        protected static void ValidateBufferArgs(byte[] buf, int off, int len)
+        {
+            if (buf == null)
+                throw new ArgumentNullException("buf");
+            if (off < 0)
+                throw new ArgumentOutOfRangeException("Buffer offset is smaller than zero.");
+            if (len < 0)
+                throw new ArgumentOutOfRangeException("Buffer length is smaller than zero.");
+            if (off + len > buf.Length)
+                throw new ArgumentOutOfRangeException("Not enough data.");
+        }
+
+        public abstract int Read(byte[] buf, int off, int len);
+
+        public int ReadAll(byte[] buf, int off, int len)
+        {
+            ValidateBufferArgs(buf, off, len);
+            int got = 0;
+
+            //If we previously peeked a byte, we need to use that first.
+            if (_hasPeekByte)
+            {
+                buf[off + got++] = _peekBuffer[0];
+                _hasPeekByte = false;
+            }
+
+            while (got < len)
+            {
+                int ret = Read(buf, off + got, len - got);
+                if (ret <= 0)
+                {
+                    throw new TTransportException(
+                        TTransportException.ExceptionType.EndOfFile,
+                        "Cannot read, Remote side has closed");
+                }
+                got += ret;
+            }
+            return got;
+        }
+
+        public virtual void Write(byte[] buf)
+        {
+            Write(buf, 0, buf.Length);
+        }
+
+        public abstract void Write(byte[] buf, int off, int len);
+
+        public virtual void Flush()
+        {
+        }
+
+        public virtual IAsyncResult BeginFlush(AsyncCallback callback, object state)
+        {
+            throw new TTransportException(
+                TTransportException.ExceptionType.Unknown,
+                "Asynchronous operations are not supported by this transport.");
+        }
+
+        public virtual void EndFlush(IAsyncResult asyncResult)
+        {
+            throw new TTransportException(
+                TTransportException.ExceptionType.Unknown,
+                "Asynchronous operations are not supported by this transport.");
+        }
+
+        #region " IDisposable Support "
+        // IDisposable
+        protected abstract void Dispose(bool disposing);
+
+        public void Dispose()
+        {
+            // Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+        #endregion
+    }
+}
diff --git a/lib/csharp/src/Transport/TTransportException.cs b/lib/csharp/src/Transport/TTransportException.cs
new file mode 100644
index 0000000..7f6cc18
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransportException.cs
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift.Transport
+{
+    public class TTransportException : TException
+    {
+        protected ExceptionType type;
+
+        public TTransportException()
+            : base()
+        {
+        }
+
+        public TTransportException(ExceptionType type)
+            : this()
+        {
+            this.type = type;
+        }
+
+        public TTransportException(ExceptionType type, string message, Exception inner = null)
+            : base(message, inner)
+        {
+            this.type = type;
+        }
+
+        public TTransportException(string message, Exception inner = null)
+            : base(message, inner)
+        {
+        }
+
+        public ExceptionType Type
+        {
+            get { return type; }
+        }
+
+        public enum ExceptionType
+        {
+            Unknown,
+            NotOpen,
+            AlreadyOpen,
+            TimedOut,
+            EndOfFile,
+            Interrupted
+        }
+    }
+}
diff --git a/lib/csharp/src/Transport/TTransportFactory.cs b/lib/csharp/src/Transport/TTransportFactory.cs
new file mode 100644
index 0000000..47a0c62
--- /dev/null
+++ b/lib/csharp/src/Transport/TTransportFactory.cs
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ * Contains some contributions under the Thrift Software License.
+ * Please see doc/old-thrift-license.txt in the Thrift distribution for
+ * details.
+ */
+
+using System;
+
+namespace Thrift.Transport
+{
+    /// <summary>
+    /// From Mark Slee &amp; 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 virtual TTransport GetTransport(TTransport trans)
+        {
+            return trans;
+        }
+    }
+}
diff --git a/lib/csharp/src/thrift.snk b/lib/csharp/src/thrift.snk
new file mode 100644
index 0000000..97bc581
--- /dev/null
+++ b/lib/csharp/src/thrift.snk
Binary files differ