THRIFT-4434: .NET Core cleanup and the beginnings of compiler unit tests
Client: netcore

This closes #1449
diff --git a/lib/netcore/Makefile.am b/lib/netcore/Makefile.am
index facee11..992558b 100644
--- a/lib/netcore/Makefile.am
+++ b/lib/netcore/Makefile.am
@@ -19,86 +19,25 @@
 
 SUBDIRS = . 
 
-THRIFT = $(top_builddir)/compiler/cpp/thrift
-
-TESTDIR = Tests/Thrift.PublicInterfaces.Compile.Tests
-GENDIR = $(TESTDIR)/gen-netcore
-
 THRIFTCODE = \
-			Thrift/Thrift.csproj \
-			Thrift/ITAsyncProcessor.cs \
-			Thrift/ITProcessorFactory.cs \
-			Thrift/SingletonTProcessorFactory.cs \
-			Thrift/TApplicationException.cs \
-			Thrift/TBaseClient.cs \
-			Thrift/TException.cs \
-			Thrift/TMultiplexedProcessor.cs \
-			Thrift/Collections/TCollections.cs \
-			Thrift/Collections/THashSet.cs \
-			Thrift/Properties/AssemblyInfo.cs \
-			Thrift/Protocols/ITProtocolFactory.cs \
-			Thrift/Protocols/TAbstractBase.cs \
-			Thrift/Protocols/TBase.cs \
-			Thrift/Protocols/TBinaryProtocol.cs \
-			Thrift/Protocols/TCompactProtocol.cs \
-			Thrift/Protocols/TJSONProtocol.cs \
-			Thrift/Protocols/TMultiplexedProtocol.cs \
-			Thrift/Protocols/TProtocol.cs \
-			Thrift/Protocols/TProtocolDecorator.cs \
-			Thrift/Protocols/TProtocolException.cs \
-			Thrift/Protocols/Entities/TField.cs \
-			Thrift/Protocols/Entities/TList.cs \
-			Thrift/Protocols/Entities/TMap.cs \
-			Thrift/Protocols/Entities/TMessage.cs \
-			Thrift/Protocols/Entities/TMessageType.cs \
-			Thrift/Protocols/Entities/TSet.cs \
-			Thrift/Protocols/Entities/TStruct.cs \
-			Thrift/Protocols/Entities/TType.cs \
-			Thrift/Protocols/Utilities/TBase64Utils.cs \
-			Thrift/Protocols/Utilities/TProtocolUtil.cs \
-			Thrift/Server/AsyncBaseServer.cs \
-			Thrift/Server/TBaseServer.cs \
-			Thrift/Server/TServerEventHandler.cs \
-			Thrift/Transports/TClientTransport.cs \
-			Thrift/Transports/TServerTransport.cs \
-			Thrift/Transports/TTransportException.cs \
-			Thrift/Transports/TTransportFactory.cs \
-			Thrift/Transports/Client/TBufferedClientTransport.cs \
-			Thrift/Transports/Client/TFramedClientTransport.cs \
-			Thrift/Transports/Client/THttpClientTransport.cs \
-			Thrift/Transports/Client/TMemoryBufferClientTransport.cs \
-			Thrift/Transports/Client/TNamedPipeClientTransport.cs \
-			Thrift/Transports/Client/TSocketClientTransport.cs \
-			Thrift/Transports/Client/TStreamClientTransport.cs \
-			Thrift/Transports/Client/TTlsSocketClientTransport.cs \
-			Thrift/Transports/Server/THttpServerTransport.cs \
-			Thrift/Transports/Server/TNamedPipeServerTransport.cs \
-			Thrift/Transports/Server/TServerFramedTransport.cs \
-			Thrift/Transports/Server/TServerSocketTransport.cs \
-			Thrift/Transports/Server/TTlsServerSocketTransport.cs 
+			Thrift/Thrift.csproj
 
 all-local: \
 	Thrift.dll
 
 Thrift.dll: $(THRIFTCODE)
-	$(MKDIR_P) $(GENDIR)
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(TESTDIR)/CassandraTest.thrift
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/test/ThriftTest.thrift
-	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/contrib/fb303/if/fb303.thrift
-	$(DOTNETCORE) --info
-	$(DOTNETCORE) restore
+#	$(MKDIR_P) $(GENDIR)
+#	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(TESTDIR)/CassandraTest.thrift
+#	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/test/ThriftTest.thrift
+#	$(THRIFT)  -gen netcore:wcf   -r  -out $(GENDIR)  $(top_srcdir)/contrib/fb303/if/fb303.thrift
 	$(DOTNETCORE) build
 
 clean-local:
-	$(RM) Thrift.dll
-	$(RM) -r $(GENDIR)
 	$(RM) -r Thrift/bin
 	$(RM) -r Thrift/obj
-	$(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin
-	$(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj
 
 EXTRA_DIST = \
-			 $(THRIFTCODE) \
+			 Thrift \
 			 Thrift.sln \
 			 Tests \
 			 README.md
diff --git a/lib/netcore/README.md b/lib/netcore/README.md
index 39492f3..94b047f 100644
--- a/lib/netcore/README.md
+++ b/lib/netcore/README.md
@@ -10,7 +10,10 @@
 - .NET Standard 1.6 (SDK 2.0.0)
 
 # How to build on Windows
+- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable
 - Open the Thrift.sln project with Visual Studio and build.
+or 
+- Build with scripts
 
 # How to build on Unix
 - Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore b/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore
new file mode 100644
index 0000000..7254c31
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore
@@ -0,0 +1,2 @@
+# ignore for autogenerated files
+/Apache
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
new file mode 100644
index 0000000..bc4afa1
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs
@@ -0,0 +1,502 @@
+// 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.Threading.Tasks;
+using KellermanSoftware.CompareNetObjects;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Transports.Client;
+
+namespace Thrift.IntegrationTests.Protocols
+{
+    [TestClass]
+    public class ProtocolsOperationsTests
+    {
+        private readonly CompareLogic _compareLogic = new CompareLogic();
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Call)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TBinaryProtocol), TMessageType.Reply)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Call)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TCompactProtocol), TMessageType.Reply)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Call)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Exception)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Oneway)]
+        [DataRow(typeof(TJsonProtocol), TMessageType.Reply)]
+        public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageType)
+        {
+            var expected = new TMessage(nameof(TMessage), messageType, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteMessageBeginAsync(expected);
+                    await protocol.WriteMessageEndAsync();
+
+                    stream.Seek(0, SeekOrigin.Begin);
+
+                    var actualMessage = await protocol.ReadMessageBeginAsync();
+                    await protocol.ReadMessageEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actualMessage);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        [ExpectedException(typeof(Exception))]
+        public async Task WriteReadStruct_Test(Type protocolType)
+        {
+            var expected = new TStruct(nameof(TStruct));
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteStructBeginAsync(expected);
+                    await protocol.WriteStructEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadStructBeginAsync();
+                    await protocol.ReadStructEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        [ExpectedException(typeof(Exception))]
+        public async Task WriteReadField_Test(Type protocolType)
+        {
+            var expected = new TField(nameof(TField), TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteFieldBeginAsync(expected);
+                    await protocol.WriteFieldEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadFieldBeginAsync();
+                    await protocol.ReadFieldEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadMap_Test(Type protocolType)
+        {
+            var expected = new TMap(TType.String, TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteMapBeginAsync(expected);
+                    await protocol.WriteMapEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadMapBeginAsync();
+                    await protocol.ReadMapEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadList_Test(Type protocolType)
+        {
+            var expected = new TList(TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteListBeginAsync(expected);
+                    await protocol.WriteListEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadListBeginAsync();
+                    await protocol.ReadListEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadSet_Test(Type protocolType)
+        {
+            var expected = new TSet(TType.String, 1);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteSetBeginAsync(expected);
+                    await protocol.WriteSetEndAsync();
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadSetBeginAsync();
+                    await protocol.ReadSetEndAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadBool_Test(Type protocolType)
+        {
+            var expected = true;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteBoolAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadBoolAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadByte_Test(Type protocolType)
+        {
+            var expected = sbyte.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteByteAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadByteAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI16_Test(Type protocolType)
+        {
+            var expected = short.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI16Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI16Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI32_Test(Type protocolType)
+        {
+            var expected = int.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI32Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI32Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadI64_Test(Type protocolType)
+        {
+            var expected = long.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteI64Async(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadI64Async();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadDouble_Test(Type protocolType)
+        {
+            var expected = double.MaxValue;
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteDoubleAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadDoubleAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadString_Test(Type protocolType)
+        {
+            var expected = nameof(String);
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteStringAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadStringAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        [DataTestMethod]
+        [DataRow(typeof(TBinaryProtocol))]
+        [DataRow(typeof(TCompactProtocol))]
+        [DataRow(typeof(TJsonProtocol))]
+        public async Task WriteReadBinary_Test(Type protocolType)
+        {
+            var expected = Encoding.UTF8.GetBytes(nameof(String));
+
+            try
+            {
+                var tuple = GetProtocolInstance(protocolType);
+                using (var stream = tuple.Item1)
+                {
+                    var protocol = tuple.Item2;
+
+                    await protocol.WriteBinaryAsync(expected);
+
+                    stream?.Seek(0, SeekOrigin.Begin);
+
+                    var actual = await protocol.ReadBinaryAsync();
+
+                    var result = _compareLogic.Compare(expected, actual);
+                    Assert.IsTrue(result.AreEqual, result.DifferencesString);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e);
+            }
+        }
+
+        private static Tuple<Stream, TProtocol> GetProtocolInstance(Type protocolType)
+        {
+            var memoryStream = new MemoryStream();
+            var streamClientTransport = new TStreamClientTransport(memoryStream, memoryStream);
+            var protocol = (TProtocol) Activator.CreateInstance(protocolType, streamClientTransport);
+            return new Tuple<Stream, TProtocol>(memoryStream, protocol);
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
new file mode 100644
index 0000000..f25dac5
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj
@@ -0,0 +1,29 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <AssemblyName>Thrift.IntegrationTests</AssemblyName>
+    <PackageId>Thrift.IntegrationTests</PackageId>
+    <OutputType>Exe</OutputType>
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
+    <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
+    <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
+    <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
+    <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="CompareNETObjects" Version="4.3.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
+    <PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
+    <PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="4.4.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+
+</Project>
\ No newline at end of file
diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore
new file mode 100644
index 0000000..ae929a3
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore
@@ -0,0 +1,4 @@
+# ignore for autogenerated files
+/ThriftTest
+/Apache
+/Facebook
diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
index f551116..c4a84a3 100644
--- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
+++ b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj
@@ -18,4 +18,19 @@
     <PackageReference Include="System.ServiceModel.Primitives" Version="[4.1.0,)" />
   </ItemGroup>
 
+  <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile">
+    <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true">
+      <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" />
+    </Exec>
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./CassandraTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../test/ThriftTest.thrift" />
+    <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+    <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+    <Exec Condition="Exists('$(ProjectDir)/../../../compiler/cpp/thrift')" Command="$(ProjectDir)/../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../../../contrib/fb303/if/fb303.thrift" />
+  </Target>
+
 </Project>
diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
new file mode 100644
index 0000000..1be99b4
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs
@@ -0,0 +1,83 @@
+// 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.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Collections;
+
+namespace Thrift.Tests.Collections
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class TCollectionsTests
+    {
+        //TODO: Add tests for IEnumerable with objects and primitive values inside
+
+        [TestMethod]
+        public void TCollection_Equals_Primitive_Test()
+        {
+            var collection1 = new List<int> {1,2,3};
+            var collection2 = new List<int> {1,2,3};
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            Assert.IsTrue(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_Primitive_Different_Test()
+        {
+            var collection1 = new List<int> { 1, 2, 3 };
+            var collection2 = new List<int> { 1, 2 };
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            Assert.IsFalse(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_Objects_Test()
+        {
+            var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+            var collection2 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            // references to different collections
+            Assert.IsFalse(result);
+        }
+
+        [TestMethod]
+        public void TCollection_Equals_OneAndTheSameObject_Test()
+        {
+            var collection1 = new List<ExampleClass> { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } };
+            var collection2 = collection1;
+
+            var result = TCollections.Equals(collection1, collection2);
+
+            // references to one and the same collection
+            Assert.IsTrue(result);
+        }
+
+        private class ExampleClass
+        {
+            public int X { get; set; }
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs
new file mode 100644
index 0000000..8de573e
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs
@@ -0,0 +1,71 @@
+// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Collections;
+
+namespace Thrift.Tests.Collections
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class THashSetTests
+    {
+        [TestMethod]
+        public void THashSet_Equals_Primitive_Test()
+        {
+            const int value = 1;
+
+            var hashSet = new THashSet<int> {value};
+            
+            Assert.IsTrue(hashSet.Contains(value));
+
+            hashSet.Remove(value);
+
+            Assert.IsTrue(hashSet.Count == 0);
+
+            hashSet.Add(value);
+
+            Assert.IsTrue(hashSet.Contains(value));
+
+            hashSet.Clear();
+
+            Assert.IsTrue(hashSet.Count == 0);
+
+            var newArr = new int[1];
+            hashSet.Add(value);
+            hashSet.CopyTo(newArr, 0);
+
+            Assert.IsTrue(newArr.Contains(value));
+
+            var en = hashSet.GetEnumerator();
+            en.MoveNext();
+
+            Assert.IsTrue((int)en.Current == value);
+            
+            using (var ien = ((IEnumerable<int>)hashSet).GetEnumerator())
+            {
+                ien.MoveNext();
+
+                Assert.IsTrue(ien.Current == value);
+            }
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs
new file mode 100644
index 0000000..cdc8317
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs
@@ -0,0 +1,172 @@
+// 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 Microsoft.VisualStudio.TestTools.UnitTesting;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Protocols.Utilities;
+
+namespace Thrift.Tests.Protocols
+{
+    [TestClass]
+    public class TJSONProtocolHelperTests
+    {
+        [TestMethod]
+        public void GetTypeNameForTypeId_Test()
+        {
+            // input/output
+            var sets = new List<Tuple<TType, byte[]>>
+            {
+                new Tuple<TType, byte[]>(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool),
+                new Tuple<TType, byte[]>(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte),
+                new Tuple<TType, byte[]>(TType.I16, TJSONProtocolConstants.TypeNames.NameI16),
+                new Tuple<TType, byte[]>(TType.I32, TJSONProtocolConstants.TypeNames.NameI32),
+                new Tuple<TType, byte[]>(TType.I64, TJSONProtocolConstants.TypeNames.NameI64),
+                new Tuple<TType, byte[]>(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble),
+                new Tuple<TType, byte[]>(TType.String, TJSONProtocolConstants.TypeNames.NameString),
+                new Tuple<TType, byte[]>(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct),
+                new Tuple<TType, byte[]>(TType.Map, TJSONProtocolConstants.TypeNames.NameMap),
+                new Tuple<TType, byte[]>(TType.Set, TJSONProtocolConstants.TypeNames.NameSet),
+                new Tuple<TType, byte[]>(TType.List, TJSONProtocolConstants.TypeNames.NameList),
+            };
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.GetTypeNameForTypeId(t.Item1) == t.Item2, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeNameForTypeId_TStop_Test()
+        {
+            TJSONProtocolHelper.GetTypeNameForTypeId(TType.Stop);
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeNameForTypeId_NonExistingTType_Test()
+        {
+            TJSONProtocolHelper.GetTypeNameForTypeId((TType)100);
+        }
+
+        [TestMethod]
+        public void GetTypeIdForTypeName_Test()
+        {
+            // input/output
+            var sets = new List<Tuple<TType, byte[]>>
+            {
+                new Tuple<TType, byte[]>(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool),
+                new Tuple<TType, byte[]>(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte),
+                new Tuple<TType, byte[]>(TType.I16, TJSONProtocolConstants.TypeNames.NameI16),
+                new Tuple<TType, byte[]>(TType.I32, TJSONProtocolConstants.TypeNames.NameI32),
+                new Tuple<TType, byte[]>(TType.I64, TJSONProtocolConstants.TypeNames.NameI64),
+                new Tuple<TType, byte[]>(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble),
+                new Tuple<TType, byte[]>(TType.String, TJSONProtocolConstants.TypeNames.NameString),
+                new Tuple<TType, byte[]>(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct),
+                new Tuple<TType, byte[]>(TType.Map, TJSONProtocolConstants.TypeNames.NameMap),
+                new Tuple<TType, byte[]>(TType.Set, TJSONProtocolConstants.TypeNames.NameSet),
+                new Tuple<TType, byte[]>(TType.List, TJSONProtocolConstants.TypeNames.NameList),
+            };
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.GetTypeIdForTypeName(t.Item2) == t.Item1, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_TStopTypeName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new []{(byte)TType.Stop, (byte)TType.Stop});
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_NonExistingTypeName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new byte[]{100});
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void GetTypeIdForTypeName_EmptyName_Test()
+        {
+            TJSONProtocolHelper.GetTypeIdForTypeName(new byte[] {});
+        }
+
+        [TestMethod]
+        public void IsJsonNumeric_Test()
+        {
+            // input/output
+            var correctJsonNumeric = "+-.0123456789Ee";
+            var incorrectJsonNumeric = "AaBcDd/*\\";
+
+            var sets = correctJsonNumeric.Select(ch => new Tuple<byte, bool>((byte) ch, true)).ToList();
+            sets.AddRange(incorrectJsonNumeric.Select(ch => new Tuple<byte, bool>((byte) ch, false)));
+
+            foreach (var t in sets)
+            {
+                Assert.IsTrue(TJSONProtocolHelper.IsJsonNumeric(t.Item1) == t.Item2, $"Wrong mapping of Char {t.Item1} to bool: {t.Item2}");
+            }
+        }
+
+        [TestMethod]
+        public void ToHexVal_Test()
+        {
+            // input/output
+            var chars = "0123456789abcdef";
+            var expectedHexValues = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+            var sets = chars.Select((ch, i) => new Tuple<char, byte>(ch, expectedHexValues[i])).ToList();
+
+            foreach (var t in sets)
+            {
+                var actualResult = TJSONProtocolHelper.ToHexVal((byte)t.Item1);
+                Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of char byte {t.Item1} to it expected hex value: {t.Item2}. Actual hex value: {actualResult}");
+            }
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(TProtocolException))]
+        public void ToHexVal_WrongInputChar_Test()
+        {
+            TJSONProtocolHelper.ToHexVal((byte)'s');
+        }
+
+        [TestMethod]
+        public void ToHexChar_Test()
+        {
+            // input/output
+            var hexValues = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+            var expectedChars = "0123456789abcdef";
+            
+
+            var sets = hexValues.Select((hv, i) => new Tuple<byte, char>(hv, expectedChars[i])).ToList();
+
+            foreach (var t in sets)
+            {
+                var actualResult = TJSONProtocolHelper.ToHexChar(t.Item1);
+                Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of hex value {t.Item1} to it expected char: {t.Item2}. Actual hex value: {actualResult}");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs
new file mode 100644
index 0000000..5237360
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.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.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using NSubstitute;
+using Thrift.Protocols;
+using Thrift.Protocols.Entities;
+using Thrift.Transports;
+using Thrift.Transports.Client;
+
+namespace Thrift.Tests.Protocols
+{
+    // ReSharper disable once InconsistentNaming
+    [TestClass]
+    public class TJSONProtocolTests
+    {
+        [TestMethod]
+        public void TJSONProtocol_Can_Create_Instance_Test()
+        {
+            var httpClientTransport = Substitute.For<THttpClientTransport>(new Uri("http://localhost"), null);
+
+            var result = new TJSONProtocolWrapper(httpClientTransport);
+
+            Assert.IsNotNull(result);
+            Assert.IsNotNull(result.WrappedContext);
+            Assert.IsNotNull(result.WrappedReader);
+            Assert.IsNotNull(result.Transport);
+            Assert.IsTrue(result.WrappedRecursionDepth == 0);
+            Assert.IsTrue(result.WrappedRecursionLimit == TProtocol.DefaultRecursionDepth);
+
+            Assert.IsTrue(result.Transport.Equals(httpClientTransport));
+            Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase));
+            Assert.IsTrue(result.WrappedReader.GetType().Name.Equals("LookaheadReader", StringComparison.OrdinalIgnoreCase));
+        }
+
+        private class TJSONProtocolWrapper : TJsonProtocol
+        {
+            public TJSONProtocolWrapper(TClientTransport trans) : base(trans)
+            {
+            }
+
+            public object WrappedContext => Context;
+            public object WrappedReader => Reader;
+            public int WrappedRecursionDepth => RecursionDepth;
+            public int WrappedRecursionLimit => RecursionLimit;
+        }
+    }
+}
diff --git a/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj
new file mode 100644
index 0000000..e46f165
--- /dev/null
+++ b/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj
@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFramework>netcoreapp2.0</TargetFramework>
+  </PropertyGroup>
+  <ItemGroup>
+    <PackageReference Include="CompareNETObjects" Version="4.3.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
+    <PackageReference Include="MSTest.TestAdapter" Version="1.2.0" />
+    <PackageReference Include="MSTest.TestFramework" Version="1.2.0" />
+    <PackageReference Include="NSubstitute" Version="3.1.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Thrift\Thrift.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/lib/netcore/Thrift.sln b/lib/netcore/Thrift.sln
index a730269..fe30aa5 100644
--- a/lib/netcore/Thrift.sln
+++ b/lib/netcore/Thrift.sln
@@ -4,10 +4,14 @@
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{0676962B-98C2-49EC-B4C4-7A0451D0640B}"
-EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "Thrift\Thrift.csproj", "{D85F572F-7D80-40A4-9A9B-2731ED187C24}"
 EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{9F9A11BF-3C95-4E80-AFBF-768541996844}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrift.Tests\Thrift.Tests.csproj", "{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A429F05B-F511-45EF-AE7B-04E1AE9C9367}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -18,18 +22,6 @@
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x64.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Debug|x86.Build.0 = Debug|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x64.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x64.Build.0 = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x86.ActiveCfg = Release|Any CPU
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B}.Release|x86.Build.0 = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -42,12 +34,50 @@
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x64.Build.0 = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.ActiveCfg = Release|Any CPU
 		{D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.Build.0 = Debug|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.Build.0 = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.ActiveCfg = Release|Any CPU
+		{9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.Build.0 = Debug|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.Build.0 = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.ActiveCfg = Release|Any CPU
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.Build.0 = Debug|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.Build.0 = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.ActiveCfg = Release|Any CPU
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
 	GlobalSection(NestedProjects) = preSolution
-		{0676962B-98C2-49EC-B4C4-7A0451D0640B} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{9F9A11BF-3C95-4E80-AFBF-768541996844} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
+		{A429F05B-F511-45EF-AE7B-04E1AE9C9367} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9}
diff --git a/lib/netcore/Thrift/Protocols/TAbstractBase.cs b/lib/netcore/Thrift/Protocols/TAbstractBase.cs
index eddb85e..4e18681 100644
--- a/lib/netcore/Thrift/Protocols/TAbstractBase.cs
+++ b/lib/netcore/Thrift/Protocols/TAbstractBase.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Protocols/TBase.cs b/lib/netcore/Thrift/Protocols/TBase.cs
index cd11099..014e1ae 100644
--- a/lib/netcore/Thrift/Protocols/TBase.cs
+++ b/lib/netcore/Thrift/Protocols/TBase.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs b/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
index fa0c5fc..deec85c 100644
--- a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -79,7 +79,7 @@
             }
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -293,15 +293,15 @@
             await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 return;
             }
 
-            await WriteI32Async(b.Length, cancellationToken);
-            await Trans.WriteAsync(b, 0, b.Length, cancellationToken);
+            await WriteI32Async(bytes.Length, cancellationToken);
+            await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
         public override async Task<TMessage> ReadMessageBeginAsync(CancellationToken cancellationToken)
@@ -511,8 +511,13 @@
 
             var i32In = new byte[4];
             await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken);
-            var result = ((i32In[0] & 0xff) << 24) | ((i32In[1] & 0xff) << 16) | ((i32In[2] & 0xff) << 8) |
-                         i32In[3] & 0xff;
+
+            var result = 
+                ((i32In[0] & 0xff) << 24) | 
+                ((i32In[1] & 0xff) << 16) | 
+                ((i32In[2] & 0xff) << 8) |
+                i32In[3] & 0xff;
+
             return result;
         }
 
diff --git a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs b/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
index 6d5e0bf..cecdf03 100644
--- a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TCompactProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -114,7 +114,7 @@
         ///     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 async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -383,16 +383,16 @@
             await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 return;
             }
 
-            var bufferTuple = CreateWriteVarInt32((uint) b.Length);
+            var bufferTuple = CreateWriteVarInt32((uint) bytes.Length);
             await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken);
-            await Trans.WriteAsync(b, 0, b.Length, cancellationToken);
+            await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken);
         }
 
         public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken)
diff --git a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs b/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
index 17aa5f7..6d33f02 100644
--- a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TJSONProtocol.cs
@@ -19,6 +19,7 @@
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
+using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
@@ -28,8 +29,6 @@
 
 namespace Thrift.Protocols
 {
-    //TODO: implementation of TProtocol
-
     /// <summary>
     ///     JSON protocol implementation for thrift.
     ///     This is a full-featured protocol supporting Write and Read.
@@ -42,53 +41,14 @@
     {
         private const long Version = 1;
 
-        private const int DefStringSize = 16;
-
-        private static readonly byte[] Comma = {(byte) ','};
-        private static readonly byte[] Colon = {(byte) ':'};
-        private static readonly byte[] Lbrace = {(byte) '{'};
-        private static readonly byte[] Rbrace = {(byte) '}'};
-        private static readonly byte[] Lbracket = {(byte) '['};
-        private static readonly byte[] Rbracket = {(byte) ']'};
-        private static readonly byte[] Quote = {(byte) '"'};
-        private static readonly byte[] Backslash = {(byte) '\\'};
-
-        private static readonly byte[] NameBool = {(byte) 't', (byte) 'f'};
-        private static readonly byte[] NameByte = {(byte) 'i', (byte) '8'};
-        private static readonly byte[] NameI16 = {(byte) 'i', (byte) '1', (byte) '6'};
-        private static readonly byte[] NameI32 = {(byte) 'i', (byte) '3', (byte) '2'};
-        private static readonly byte[] NameI64 = {(byte) 'i', (byte) '6', (byte) '4'};
-        private static readonly byte[] NameDouble = {(byte) 'd', (byte) 'b', (byte) 'l'};
-        private static readonly byte[] NameStruct = {(byte) 'r', (byte) 'e', (byte) 'c'};
-        private static readonly byte[] NameString = {(byte) 's', (byte) 't', (byte) 'r'};
-        private static readonly byte[] NameMap = {(byte) 'm', (byte) 'a', (byte) 'p'};
-        private static readonly byte[] NameList = {(byte) 'l', (byte) 's', (byte) 't'};
-        private static readonly byte[] NameSet = {(byte) 's', (byte) 'e', (byte) 't'};
-
-        private readonly char[] _escapeChars = "\"\\/bfnrt".ToCharArray();
-
-        private readonly byte[] _escapeCharVals =
-        {
-            (byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'
-        };
-
-        private readonly byte[] _escseq = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'};
-
-        private readonly byte[] _jsonCharTable =
-        {
-            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
-        };
-
         // Temporary buffer used by several methods
         private readonly byte[] _tempBuffer = new byte[4];
 
         // Current context that we are in
-        protected JsonBaseContext Context;
+        protected JSONBaseContext Context;
 
         // Stack of nested contexts that we may be in
-        protected Stack<JsonBaseContext> ContextStack = new Stack<JsonBaseContext>();
+        protected Stack<JSONBaseContext> ContextStack = new Stack<JSONBaseContext>();
 
         // Reader that manages a 1-byte buffer
         protected LookaheadReader Reader;
@@ -102,105 +62,14 @@
         public TJsonProtocol(TClientTransport trans)
             : base(trans)
         {
-            //throw new NotImplementedException("TJsonProtocol is not fully ready for usage");
-
-            Context = new JsonBaseContext(this);
+            Context = new JSONBaseContext(this);
             Reader = new LookaheadReader(this);
         }
 
-        private static byte[] GetTypeNameForTypeId(TType typeId)
-        {
-            switch (typeId)
-            {
-                case TType.Bool:
-                    return NameBool;
-                case TType.Byte:
-                    return NameByte;
-                case TType.I16:
-                    return NameI16;
-                case TType.I32:
-                    return NameI32;
-                case TType.I64:
-                    return NameI64;
-                case TType.Double:
-                    return NameDouble;
-                case TType.String:
-                    return NameString;
-                case TType.Struct:
-                    return NameStruct;
-                case TType.Map:
-                    return NameMap;
-                case TType.Set:
-                    return NameSet;
-                case TType.List:
-                    return NameList;
-                default:
-                    throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
-            }
-        }
-
-        private static TType GetTypeIdForTypeName(byte[] name)
-        {
-            var 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 exType");
-            }
-            return result;
-        }
-
         /// <summary>
         ///     Push a new JSON context onto the stack.
         /// </summary>
-        protected void PushContext(JsonBaseContext c)
+        protected void PushContext(JSONBaseContext c)
         {
             ContextStack.Push(Context);
             Context = c;
@@ -219,94 +88,60 @@
         ///     Marked protected to avoid synthetic accessor in JSONListContext.Read
         ///     and JSONPairContext.Read
         /// </summary>
-        protected async Task ReadJsonSyntaxCharAsync(byte[] b, CancellationToken cancellationToken)
+        protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             var ch = await Reader.ReadAsync(cancellationToken);
-            if (ch != b[0])
+            if (ch != bytes[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');
-            }
-
-            if ((ch >= 'a') && (ch <= 'f'))
-            {
-                ch += 10;
-                return (byte) ((char) ch - 'a');
-            }
-
-            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');
-            }
-            val -= 10;
-            return (byte) ((char) val + 'a');
-        }
-
-        /// <summary>
         ///     Write the bytes in array buf as a JSON characters, escaping as needed
         /// </summary>
-        private async Task WriteJsonStringAsync(byte[] b, CancellationToken cancellationToken)
+        private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
-            var len = b.Length;
+            var len = bytes.Length;
             for (var i = 0; i < len; i++)
             {
-                if ((b[i] & 0x00FF) >= 0x30)
+                if ((bytes[i] & 0x00FF) >= 0x30)
                 {
-                    if (b[i] == Backslash[0])
+                    if (bytes[i] == TJSONProtocolConstants.Backslash[0])
                     {
-                        await Trans.WriteAsync(Backslash, cancellationToken);
-                        await Trans.WriteAsync(Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
                     }
                     else
                     {
-                        await Trans.WriteAsync(b, i, 1, cancellationToken);
+                        await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken);
                     }
                 }
                 else
                 {
-                    _tempBuffer[0] = _jsonCharTable[b[i]];
+                    _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]];
                     if (_tempBuffer[0] == 1)
                     {
-                        await Trans.WriteAsync(b, i, 1, cancellationToken);
+                        await Trans.WriteAsync(bytes, i, 1, cancellationToken);
                     }
                     else if (_tempBuffer[0] > 1)
                     {
-                        await Trans.WriteAsync(Backslash, cancellationToken);
+                        await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken);
                         await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken);
                     }
                     else
                     {
-                        await Trans.WriteAsync(_escseq, cancellationToken);
-                        _tempBuffer[0] = HexChar((byte) (b[i] >> 4));
-                        _tempBuffer[1] = HexChar(b[i]);
+                        await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken);
+                        _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4));
+                        _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]);
                         await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken);
                     }
                 }
             }
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
         }
 
         /// <summary>
@@ -321,14 +156,15 @@
             var escapeNum = Context.EscapeNumbers();
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
-            await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken);
+            var bytes = Utf8Encoding.GetBytes(str);
+            await Trans.WriteAsync(bytes, cancellationToken);
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
         }
 
@@ -361,14 +197,14 @@
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken);
 
             if (escapeNum)
             {
-                await Trans.WriteAsync(Quote, cancellationToken);
+                await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
         }
 
@@ -376,18 +212,18 @@
         ///     Write out contents of byte array b as a JSON string with base-64 encoded
         ///     data
         /// </summary>
-        private async Task WriteJsonBase64Async(byte[] b, CancellationToken cancellationToken)
+        private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
-            var len = b.Length;
+            var len = bytes.Length;
             var off = 0;
 
             while (len >= 3)
             {
                 // Encode 3 bytes at a time
-                TBase64Utils.Encode(b, off, 3, _tempBuffer, 0);
+                TBase64Helper.Encode(bytes, off, 3, _tempBuffer, 0);
                 await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken);
                 off += 3;
                 len -= 3;
@@ -396,37 +232,37 @@
             if (len > 0)
             {
                 // Encode remainder
-                TBase64Utils.Encode(b, off, len, _tempBuffer, 0);
+                TBase64Helper.Encode(bytes, off, len, _tempBuffer, 0);
                 await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken);
             }
 
-            await Trans.WriteAsync(Quote, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken);
         }
 
         private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Lbrace, cancellationToken);
-            PushContext(new JsonPairContext(this));
+            await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken);
+            PushContext(new JSONPairContext(this));
         }
 
         private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken)
         {
             PopContext();
-            await Trans.WriteAsync(Rbrace, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken);
         }
 
         private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken)
         {
             await Context.WriteAsync(cancellationToken);
-            await Trans.WriteAsync(Lbracket, cancellationToken);
-            PushContext(new JsonListContext(this));
+            await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken);
+            PushContext(new JSONListContext(this));
         }
 
         private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken)
         {
             PopContext();
-            await Trans.WriteAsync(Rbracket, cancellationToken);
+            await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken);
         }
 
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
@@ -446,7 +282,7 @@
             await WriteJsonArrayEndAsync(cancellationToken);
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
             await WriteJsonObjectStartAsync(cancellationToken);
         }
@@ -460,7 +296,7 @@
         {
             await WriteJsonIntegerAsync(field.ID, cancellationToken);
             await WriteJsonObjectStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(field.Type), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken);
         }
 
         public override async Task WriteFieldEndAsync(CancellationToken cancellationToken)
@@ -479,8 +315,8 @@
         public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(map.KeyType), cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(map.ValueType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken);
             await WriteJsonIntegerAsync(map.Count, cancellationToken);
             await WriteJsonObjectStartAsync(cancellationToken);
         }
@@ -494,7 +330,7 @@
         public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(list.ElementType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken);
             await WriteJsonIntegerAsync(list.Count, cancellationToken);
         }
 
@@ -506,7 +342,7 @@
         public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken)
         {
             await WriteJsonArrayStartAsync(cancellationToken);
-            await WriteJsonStringAsync(GetTypeNameForTypeId(set.ElementType), cancellationToken);
+            await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken);
             await WriteJsonIntegerAsync(set.Count, cancellationToken);
         }
 
@@ -551,9 +387,9 @@
             await WriteJsonStringAsync(b, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
-            await WriteJsonBase64Async(b, cancellationToken);
+            await WriteJsonBase64Async(bytes, cancellationToken);
         }
 
         /// <summary>
@@ -572,18 +408,18 @@
                     await Context.ReadAsync(cancellationToken);
                 }
 
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
 
                 while (true)
                 {
                     var ch = await Reader.ReadAsync(cancellationToken);
-                    if (ch == Quote[0])
+                    if (ch == TJSONProtocolConstants.Quote[0])
                     {
                         break;
                     }
 
                     // escaped?
-                    if (ch != _escseq[0])
+                    if (ch != TJSONProtocolConstants.EscSequences[0])
                     {
                         await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken);
                         continue;
@@ -591,26 +427,25 @@
 
                     // distinguish between \uXXXX and \?
                     ch = await Reader.ReadAsync(cancellationToken);
-                    if (ch != _escseq[1]) // control chars like \n
+                    if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n
                     {
-                        var off = Array.IndexOf(_escapeChars, (char) ch);
+                        var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch);
                         if (off == -1)
                         {
                             throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char");
                         }
-                        ch = _escapeCharVals[off];
+                        ch = TJSONProtocolConstants.EscapeCharValues[off];
                         await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken);
                         continue;
                     }
 
-
                     // it's \uXXXX
                     await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken);
 
-                    var wch = (short) ((HexVal(_tempBuffer[0]) << 12) +
-                                       (HexVal(_tempBuffer[1]) << 8) +
-                                       (HexVal(_tempBuffer[2]) << 4) +
-                                       HexVal(_tempBuffer[3]));
+                    var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) +
+                                       (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) +
+                                       (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) +
+                                       TJSONProtocolHelper.ToHexVal(_tempBuffer[3]));
 
                     if (char.IsHighSurrogate((char) wch))
                     {
@@ -649,34 +484,6 @@
         }
 
         /// <summary>
-        ///     Return true if the given byte could be a valid part of a JSON number.
-        /// </summary>
-        private static 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>
@@ -685,12 +492,21 @@
             var strbld = new StringBuilder();
             while (true)
             {
-                var ch = await Reader.PeekAsync(cancellationToken);
-                if (!IsJsonNumeric(ch))
+                //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions
+                try
+                {
+                    var ch = await Reader.PeekAsync(cancellationToken);
+                    if (!TJSONProtocolHelper.IsJsonNumeric(ch))
+                    {
+                        break;
+                    }
+                    var c = (char)await Reader.ReadAsync(cancellationToken);
+                    strbld.Append(c);
+                }
+                catch (TTransportException)
                 {
                     break;
                 }
-                strbld.Append((char) await Reader.ReadAsync(cancellationToken));
             }
             return strbld.ToString();
         }
@@ -703,13 +519,13 @@
             await Context.ReadAsync(cancellationToken);
             if (Context.EscapeNumbers())
             {
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             var str = await ReadJsonNumericCharsAsync(cancellationToken);
             if (Context.EscapeNumbers())
             {
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             try
@@ -729,7 +545,7 @@
         private async Task<double> ReadJsonDoubleAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            if (await Reader.PeekAsync(cancellationToken) == Quote[0])
+            if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0])
             {
                 var arr = await ReadJsonStringAsync(true, cancellationToken);
                 var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
@@ -746,7 +562,7 @@
             if (Context.EscapeNumbers())
             {
                 // This will throw - we should have had a quote if escapeNum == true
-                await ReadJsonSyntaxCharAsync(Quote, cancellationToken);
+                await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken);
             }
 
             try
@@ -779,7 +595,7 @@
             while (len > 4)
             {
                 // Decode 4 bytes at a time
-                TBase64Utils.Decode(b, off, 4, b, size); // NB: decoded in place
+                TBase64Helper.Decode(b, off, 4, b, size); // NB: decoded in place
                 off += 4;
                 len -= 4;
                 size += 3;
@@ -790,7 +606,7 @@
             if (len > 1)
             {
                 // Decode remainder
-                TBase64Utils.Decode(b, off, len, b, size); // NB: decoded in place
+                TBase64Helper.Decode(b, off, len, b, size); // NB: decoded in place
                 size += len - 1;
             }
 
@@ -803,26 +619,26 @@
         private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            await ReadJsonSyntaxCharAsync(Lbrace, cancellationToken);
-            PushContext(new JsonPairContext(this));
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken);
+            PushContext(new JSONPairContext(this));
         }
 
         private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken)
         {
-            await ReadJsonSyntaxCharAsync(Rbrace, cancellationToken);
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken);
             PopContext();
         }
 
         private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken)
         {
             await Context.ReadAsync(cancellationToken);
-            await ReadJsonSyntaxCharAsync(Lbracket, cancellationToken);
-            PushContext(new JsonListContext(this));
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken);
+            PushContext(new JSONListContext(this));
         }
 
         private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken)
         {
-            await ReadJsonSyntaxCharAsync(Rbracket, cancellationToken);
+            await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken);
             PopContext();
         }
 
@@ -862,7 +678,7 @@
         {
             var field = new TField();
             var ch = await Reader.PeekAsync(cancellationToken);
-            if (ch == Rbrace[0])
+            if (ch == TJSONProtocolConstants.RightBrace[0])
             {
                 field.Type = TType.Stop;
             }
@@ -870,7 +686,7 @@
             {
                 field.ID = (short) await ReadJsonIntegerAsync(cancellationToken);
                 await ReadJsonObjectStartAsync(cancellationToken);
-                field.Type = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+                field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             }
             return field;
         }
@@ -884,8 +700,8 @@
         {
             var map = new TMap();
             await ReadJsonArrayStartAsync(cancellationToken);
-            map.KeyType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
-            map.ValueType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             map.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             await ReadJsonObjectStartAsync(cancellationToken);
             return map;
@@ -901,7 +717,7 @@
         {
             var list = new TList();
             await ReadJsonArrayStartAsync(cancellationToken);
-            list.ElementType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             list.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             return list;
         }
@@ -915,7 +731,7 @@
         {
             var set = new TSet();
             await ReadJsonArrayStartAsync(cancellationToken);
-            set.ElementType = GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
+            set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken));
             set.Count = (int) await ReadJsonIntegerAsync(cancellationToken);
             return set;
         }
@@ -982,11 +798,11 @@
         ///     inserting/Reading additional JSON syntax characters
         ///     This base context does nothing.
         /// </summary>
-        protected class JsonBaseContext
+        protected class JSONBaseContext
         {
             protected TJsonProtocol Proto;
 
-            public JsonBaseContext(TJsonProtocol proto)
+            public JSONBaseContext(TJsonProtocol proto)
             {
                 Proto = proto;
             }
@@ -1017,11 +833,11 @@
         ///     Context for JSON lists. Will insert/Read commas before each item except
         ///     for the first one
         /// </summary>
-        protected class JsonListContext : JsonBaseContext
+        protected class JSONListContext : JSONBaseContext
         {
             private bool _first = true;
 
-            public JsonListContext(TJsonProtocol protocol)
+            public JSONListContext(TJsonProtocol protocol)
                 : base(protocol)
             {
             }
@@ -1034,7 +850,7 @@
                 }
                 else
                 {
-                    await Proto.Trans.WriteAsync(Comma, cancellationToken);
+                    await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken);
                 }
             }
 
@@ -1046,7 +862,7 @@
                 }
                 else
                 {
-                    await Proto.ReadJsonSyntaxCharAsync(Comma, cancellationToken);
+                    await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken);
                 }
             }
         }
@@ -1057,13 +873,14 @@
         ///     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
+        // ReSharper disable once InconsistentNaming
+        protected class JSONPairContext : JSONBaseContext
         {
             private bool _colon = true;
 
             private bool _first = true;
 
-            public JsonPairContext(TJsonProtocol proto)
+            public JSONPairContext(TJsonProtocol proto)
                 : base(proto)
             {
             }
@@ -1077,7 +894,7 @@
                 }
                 else
                 {
-                    await Proto.Trans.WriteAsync(_colon ? Colon : Comma, cancellationToken);
+                    await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken);
                     _colon = !_colon;
                 }
             }
@@ -1091,7 +908,7 @@
                 }
                 else
                 {
-                    await Proto.ReadJsonSyntaxCharAsync(_colon ? Colon : Comma, cancellationToken);
+                    await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken);
                     _colon = !_colon;
                 }
             }
@@ -1134,6 +951,7 @@
                 }
                 else
                 {
+                    // find more easy way to avoid exception on reading primitive types
                     await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken);
                 }
                 return _data[0];
@@ -1152,6 +970,7 @@
 
                 if (!_hasData)
                 {
+                    // find more easy way to avoid exception on reading primitive types
                     await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken);
                 }
                 _hasData = true;
diff --git a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs b/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
index 5b2202e..367e4e6 100644
--- a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs
@@ -74,22 +74,13 @@
             _serviceName = serviceName;
         }
 
-        /**
-         * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
-         * Args:
-         *   tMessage     The original message.
-         */
-
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
         {
             switch (message.Type)
             {
                 case TMessageType.Call:
                 case TMessageType.Oneway:
-                    await
-                        base.WriteMessageBeginAsync(
-                            new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID),
-                            cancellationToken);
+                    await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken);
                     break;
                 default:
                     await base.WriteMessageBeginAsync(message, cancellationToken);
@@ -97,4 +88,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Protocols/TProtocol.cs b/lib/netcore/Thrift/Protocols/TProtocol.cs
index 8fef861..91e009d 100644
--- a/lib/netcore/Thrift/Protocols/TProtocol.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocol.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -27,7 +27,7 @@
     // ReSharper disable once InconsistentNaming
     public abstract class TProtocol : IDisposable
     {
-        private const int DefaultRecursionDepth = 64;
+        public const int DefaultRecursionDepth = 64;
         private bool _isDisposed;
         protected int RecursionDepth;
 
@@ -42,7 +42,6 @@
 
         public TClientTransport Transport => Trans;
 
-        //TODO: check for protected
         protected int RecursionLimit { get; set; }
 
         public void Dispose()
@@ -93,12 +92,12 @@
 
         public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken);
 
-        public virtual async Task WriteStructBeginAsync(TStruct struc)
+        public virtual async Task WriteStructBeginAsync(TStruct @struct)
         {
-            await WriteStructBeginAsync(struc, CancellationToken.None);
+            await WriteStructBeginAsync(@struct, CancellationToken.None);
         }
 
-        public abstract Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken);
+        public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken);
 
         public virtual async Task WriteStructEndAsync()
         {
@@ -223,12 +222,12 @@
             await WriteBinaryAsync(bytes, cancellationToken);
         }
 
-        public virtual async Task WriteBinaryAsync(byte[] b)
+        public virtual async Task WriteBinaryAsync(byte[] bytes)
         {
-            await WriteBinaryAsync(b, CancellationToken.None);
+            await WriteBinaryAsync(bytes, CancellationToken.None);
         }
 
-        public abstract Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken);
+        public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken);
 
         public virtual async Task<TMessage> ReadMessageBeginAsync()
         {
diff --git a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs b/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
index 458b117..3222754 100644
--- a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -36,12 +36,7 @@
         protected TProtocolDecorator(TProtocol protocol)
             : base(protocol.Transport)
         {
-            if (protocol == null)
-            {
-                throw new ArgumentNullException(nameof(protocol));
-            }
-
-            _wrappedProtocol = protocol;
+            _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol));
         }
 
         public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken)
@@ -54,9 +49,9 @@
             await _wrappedProtocol.WriteMessageEndAsync(cancellationToken);
         }
 
-        public override async Task WriteStructBeginAsync(TStruct struc, CancellationToken cancellationToken)
+        public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken)
         {
-            await _wrappedProtocol.WriteStructBeginAsync(struc, cancellationToken);
+            await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken);
         }
 
         public override async Task WriteStructEndAsync(CancellationToken cancellationToken)
@@ -144,9 +139,9 @@
             await _wrappedProtocol.WriteStringAsync(s, cancellationToken);
         }
 
-        public override async Task WriteBinaryAsync(byte[] b, CancellationToken cancellationToken)
+        public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken)
         {
-            await _wrappedProtocol.WriteBinaryAsync(b, cancellationToken);
+            await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken);
         }
 
         public override async Task<TMessage> ReadMessageBeginAsync(CancellationToken cancellationToken)
diff --git a/lib/netcore/Thrift/Protocols/TProtocolException.cs b/lib/netcore/Thrift/Protocols/TProtocolException.cs
index 02d0d3f..8c67c3b 100644
--- a/lib/netcore/Thrift/Protocols/TProtocolException.cs
+++ b/lib/netcore/Thrift/Protocols/TProtocolException.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -15,11 +15,12 @@
 // specific language governing permissions and limitations
 // under the License.
 
+// ReSharper disable InconsistentNaming
 namespace Thrift.Protocols
 {
     public class TProtocolException : TException
     {
-        // do not rename public contants - they used in generated files
+        // do not rename public constants - they used in generated files
         public const int UNKNOWN = 0;
         public const int INVALID_DATA = 1;
         public const int NEGATIVE_SIZE = 2;
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs b/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs
new file mode 100644
index 0000000..7eff5e1
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs
@@ -0,0 +1,101 @@
+// 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.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    internal static class TBase64Helper
+    {
+        //TODO: Constants
+        //TODO: Check for args
+        //TODO: Unitests
+
+        internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+        private static readonly int[] DecodeTable =
+        {
+            -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 Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff)
+        {
+            if (src == null)
+            {
+                throw new ArgumentNullException(nameof(src));
+            }
+
+            dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F];
+
+            if (len == 3)
+            {
+                dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)];
+                dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F];
+            }
+            else if (len == 2)
+            {
+                dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)];
+                dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C];
+            }
+            else
+            {
+                // len == 1
+                dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30];
+            }
+        }
+
+        internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff)
+        {
+            if (src == null)
+            {
+                throw new ArgumentNullException(nameof(src));
+            }
+
+            dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4));
+
+            if (len > 2)
+            {
+                dst[dstOff + 1] =
+                    (byte)
+                    (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2));
+                if (len > 3)
+                {
+                    dst[dstOff + 2] =
+                        (byte)
+                        (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs
new file mode 100644
index 0000000..93eff78
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs
@@ -0,0 +1,61 @@
+// 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.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    public static class TJSONProtocolConstants
+    {
+        //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/)
+        // can be possible to get better performance and also better GC
+
+        public static readonly byte[] Comma = {(byte) ','};
+        public static readonly byte[] Colon = {(byte) ':'};
+        public static readonly byte[] LeftBrace = {(byte) '{'};
+        public static readonly byte[] RightBrace = {(byte) '}'};
+        public static readonly byte[] LeftBracket = {(byte) '['};
+        public static readonly byte[] RightBracket = {(byte) ']'};
+        public static readonly byte[] Quote = {(byte) '"'};
+        public static readonly byte[] Backslash = {(byte) '\\'};
+
+        public static readonly byte[] JsonCharTable =
+        {
+            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
+        };
+
+        public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray();
+        public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'};
+        public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'};
+
+        public static class TypeNames
+        {
+            public static readonly byte[] NameBool = { (byte)'t', (byte)'f' };
+            public static readonly byte[] NameByte = { (byte)'i', (byte)'8' };
+            public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' };
+            public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' };
+            public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' };
+            public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' };
+            public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' };
+            public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' };
+            public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' };
+            public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' };
+            public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' };
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs
new file mode 100644
index 0000000..adc26a9
--- /dev/null
+++ b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.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.
+
+using Thrift.Protocols.Entities;
+
+namespace Thrift.Protocols.Utilities
+{
+    // ReSharper disable once InconsistentNaming
+    public static class TJSONProtocolHelper
+    {
+        public static byte[] GetTypeNameForTypeId(TType typeId)
+        {
+            switch (typeId)
+            {
+                case TType.Bool:
+                    return TJSONProtocolConstants.TypeNames.NameBool;
+                case TType.Byte:
+                    return TJSONProtocolConstants.TypeNames.NameByte;
+                case TType.I16:
+                    return TJSONProtocolConstants.TypeNames.NameI16;
+                case TType.I32:
+                    return TJSONProtocolConstants.TypeNames.NameI32;
+                case TType.I64:
+                    return TJSONProtocolConstants.TypeNames.NameI64;
+                case TType.Double:
+                    return TJSONProtocolConstants.TypeNames.NameDouble;
+                case TType.String:
+                    return TJSONProtocolConstants.TypeNames.NameString;
+                case TType.Struct:
+                    return TJSONProtocolConstants.TypeNames.NameStruct;
+                case TType.Map:
+                    return TJSONProtocolConstants.TypeNames.NameMap;
+                case TType.Set:
+                    return TJSONProtocolConstants.TypeNames.NameSet;
+                case TType.List:
+                    return TJSONProtocolConstants.TypeNames.NameList;
+                default:
+                    throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType");
+            }
+        }
+
+        public static TType GetTypeIdForTypeName(byte[] name)
+        {
+            var 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 exType");
+            }
+            return result;
+        }
+
+        /// <summary>
+        ///     Return true if the given byte could be a valid part of a JSON number.
+        /// </summary>
+        public static 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;
+                default:
+                    return false;
+            }
+        }
+
+        /// <summary>
+        ///     Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
+        ///     corresponding hex value
+        /// </summary>
+        public static byte ToHexVal(byte ch)
+        {
+            if (ch >= '0' && ch <= '9')
+            {
+                return (byte)((char)ch - '0');
+            }
+
+            if (ch >= 'a' && ch <= 'f')
+            {
+                ch += 10;
+                return (byte)((char)ch - 'a');
+            }
+
+            throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character");
+        }
+
+        /// <summary>
+        ///     Convert a byte containing a hex value to its corresponding hex character
+        /// </summary>
+        public static byte ToHexChar(byte val)
+        {
+            val &= 0x0F;
+            if (val < 10)
+            {
+                return (byte)((char)val + '0');
+            }
+            val -= 10;
+            return (byte)((char)val + 'a');
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs b/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
index 038edb9..50b0385 100644
--- a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
+++ b/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs
@@ -19,83 +19,83 @@
 using System.Threading.Tasks;
 using Thrift.Protocols.Entities;
 
-namespace Thrift.Protocols
+namespace Thrift.Protocols.Utilities
 {
     // ReSharper disable once InconsistentNaming
     public static class TProtocolUtil
     {
-        public static async Task SkipAsync(TProtocol prot, TType type, CancellationToken cancellationToken)
+        public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
                 await Task.FromCanceled(cancellationToken);
             }
 
-            prot.IncrementRecursionDepth();
+            protocol.IncrementRecursionDepth();
             try
             {
                 switch (type)
                 {
                     case TType.Bool:
-                        await prot.ReadBoolAsync(cancellationToken);
+                        await protocol.ReadBoolAsync(cancellationToken);
                         break;
                     case TType.Byte:
-                        await prot.ReadByteAsync(cancellationToken);
+                        await protocol.ReadByteAsync(cancellationToken);
                         break;
                     case TType.I16:
-                        await prot.ReadI16Async(cancellationToken);
+                        await protocol.ReadI16Async(cancellationToken);
                         break;
                     case TType.I32:
-                        await prot.ReadI32Async(cancellationToken);
+                        await protocol.ReadI32Async(cancellationToken);
                         break;
                     case TType.I64:
-                        await prot.ReadI64Async(cancellationToken);
+                        await protocol.ReadI64Async(cancellationToken);
                         break;
                     case TType.Double:
-                        await prot.ReadDoubleAsync(cancellationToken);
+                        await protocol.ReadDoubleAsync(cancellationToken);
                         break;
                     case TType.String:
                         // Don't try to decode the string, just skip it.
-                        await prot.ReadBinaryAsync(cancellationToken);
+                        await protocol.ReadBinaryAsync(cancellationToken);
                         break;
                     case TType.Struct:
-                        await prot.ReadStructBeginAsync(cancellationToken);
+                        await protocol.ReadStructBeginAsync(cancellationToken);
                         while (true)
                         {
-                            var field = await prot.ReadFieldBeginAsync(cancellationToken);
+                            var field = await protocol.ReadFieldBeginAsync(cancellationToken);
                             if (field.Type == TType.Stop)
                             {
                                 break;
                             }
-                            await SkipAsync(prot, field.Type, cancellationToken);
-                            await prot.ReadFieldEndAsync(cancellationToken);
+                            await SkipAsync(protocol, field.Type, cancellationToken);
+                            await protocol.ReadFieldEndAsync(cancellationToken);
                         }
-                        await prot.ReadStructEndAsync(cancellationToken);
+                        await protocol.ReadStructEndAsync(cancellationToken);
                         break;
                     case TType.Map:
-                        var map = await prot.ReadMapBeginAsync(cancellationToken);
+                        var map = await protocol.ReadMapBeginAsync(cancellationToken);
                         for (var i = 0; i < map.Count; i++)
                         {
-                            await SkipAsync(prot, map.KeyType, cancellationToken);
-                            await SkipAsync(prot, map.ValueType, cancellationToken);
+                            await SkipAsync(protocol, map.KeyType, cancellationToken);
+                            await SkipAsync(protocol, map.ValueType, cancellationToken);
                         }
-                        await prot.ReadMapEndAsync(cancellationToken);
+                        await protocol.ReadMapEndAsync(cancellationToken);
                         break;
                     case TType.Set:
-                        var set = await prot.ReadSetBeginAsync(cancellationToken);
+                        var set = await protocol.ReadSetBeginAsync(cancellationToken);
                         for (var i = 0; i < set.Count; i++)
                         {
-                            await SkipAsync(prot, set.ElementType, cancellationToken);
+                            await SkipAsync(protocol, set.ElementType, cancellationToken);
                         }
-                        await prot.ReadSetEndAsync(cancellationToken);
+                        await protocol.ReadSetEndAsync(cancellationToken);
                         break;
                     case TType.List:
-                        var list = await prot.ReadListBeginAsync(cancellationToken);
+                        var list = await protocol.ReadListBeginAsync(cancellationToken);
                         for (var i = 0; i < list.Count; i++)
                         {
-                            await SkipAsync(prot, list.ElementType, cancellationToken);
+                            await SkipAsync(protocol, list.ElementType, cancellationToken);
                         }
-                        await prot.ReadListEndAsync(cancellationToken);
+                        await protocol.ReadListEndAsync(cancellationToken);
                         break;
                     default:
                         throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
@@ -103,8 +103,8 @@
             }
             finally
             {
-                prot.DecrementRecursionDepth();
+                protocol.DecrementRecursionDepth();
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Server/AsyncBaseServer.cs b/lib/netcore/Thrift/Server/AsyncBaseServer.cs
index 5ff7a32..0032ca3 100644
--- a/lib/netcore/Thrift/Server/AsyncBaseServer.cs
+++ b/lib/netcore/Thrift/Server/AsyncBaseServer.cs
@@ -57,8 +57,7 @@
             try
             {
                 // cancelation token
-                _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken),
-                    TaskCreationOptions.LongRunning);
+                _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken), TaskCreationOptions.LongRunning);
                 await _serverTask;
             }
             catch (Exception ex)
@@ -87,7 +86,7 @@
                     try
                     {
                         var client = await ServerTransport.AcceptAsync(cancellationToken);
-                        await Task.Factory.StartNew(() => Execute(client, cancellationToken));
+                        await Task.Factory.StartNew(() => Execute(client, cancellationToken), cancellationToken);
                     }
                     catch (TTransportException ttx)
                     {
@@ -136,8 +135,7 @@
 
                 if (ServerEventHandler != null)
                 {
-                    connectionContext =
-                        await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken);
+                    connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken);
                 }
 
                 while (!cancellationToken.IsCancellationRequested)
@@ -149,8 +147,7 @@
 
                     if (ServerEventHandler != null)
                     {
-                        await
-                            ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken);
+                        await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken);
                     }
 
                     if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken))
@@ -170,9 +167,7 @@
 
             if (ServerEventHandler != null)
             {
-                await
-                    ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol,
-                        cancellationToken);
+                await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken);
             }
 
             inputTransport?.Close();
@@ -181,4 +176,4 @@
             Logger.LogTrace("Completed client request processing");
         }
     }
-}
\ No newline at end of file
+}
diff --git a/lib/netcore/Thrift/Server/TBaseServer.cs b/lib/netcore/Thrift/Server/TBaseServer.cs
index 97cc7ff..741dd5c 100644
--- a/lib/netcore/Thrift/Server/TBaseServer.cs
+++ b/lib/netcore/Thrift/Server/TBaseServer.cs
@@ -42,20 +42,13 @@
             ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory,
             ILogger logger)
         {
-            if (itProcessorFactory == null) throw new ArgumentNullException(nameof(itProcessorFactory));
-            if (inputTransportFactory == null) throw new ArgumentNullException(nameof(inputTransportFactory));
-            if (outputTransportFactory == null) throw new ArgumentNullException(nameof(outputTransportFactory));
-            if (inputProtocolFactory == null) throw new ArgumentNullException(nameof(inputProtocolFactory));
-            if (outputProtocolFactory == null) throw new ArgumentNullException(nameof(outputProtocolFactory));
-            if (logger == null) throw new ArgumentNullException(nameof(logger));
-
-            ItProcessorFactory = itProcessorFactory;
+            ItProcessorFactory = itProcessorFactory ?? throw new ArgumentNullException(nameof(itProcessorFactory));
             ServerTransport = serverTransport;
-            InputTransportFactory = inputTransportFactory;
-            OutputTransportFactory = outputTransportFactory;
-            InputProtocolFactory = inputProtocolFactory;
-            OutputProtocolFactory = outputProtocolFactory;
-            Logger = logger;
+            InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory));
+            OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory));
+            InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory));
+            OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory));
+            Logger = logger ?? throw new ArgumentNullException(nameof(logger));
         }
 
         public void SetEventHandler(TServerEventHandler seh)
diff --git a/lib/netcore/Thrift/TApplicationException.cs b/lib/netcore/Thrift/TApplicationException.cs
index f1ea252..9ec145a 100644
--- a/lib/netcore/Thrift/TApplicationException.cs
+++ b/lib/netcore/Thrift/TApplicationException.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -19,6 +19,7 @@
 using System.Threading.Tasks;
 using Thrift.Protocols;
 using Thrift.Protocols.Entities;
+using Thrift.Protocols.Utilities;
 
 namespace Thrift
 {
@@ -60,15 +61,15 @@
             Type = type;
         }
 
-        public static async Task<TApplicationException> ReadAsync(TProtocol iprot, CancellationToken cancellationToken)
+        public static async Task<TApplicationException> ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken)
         {
             string message = null;
             var type = ExceptionType.Unknown;
 
-            await iprot.ReadStructBeginAsync(cancellationToken);
+            await inputProtocol.ReadStructBeginAsync(cancellationToken);
             while (true)
             {
-                var field = await iprot.ReadFieldBeginAsync(cancellationToken);
+                var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken);
                 if (field.Type == TType.Stop)
                 {
                     break;
@@ -79,37 +80,37 @@
                     case MessageTypeFieldId:
                         if (field.Type == TType.String)
                         {
-                            message = await iprot.ReadStringAsync(cancellationToken);
+                            message = await inputProtocol.ReadStringAsync(cancellationToken);
                         }
                         else
                         {
-                            await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                            await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         }
                         break;
                     case ExTypeFieldId:
                         if (field.Type == TType.I32)
                         {
-                            type = (ExceptionType) await iprot.ReadI32Async(cancellationToken);
+                            type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken);
                         }
                         else
                         {
-                            await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                            await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         }
                         break;
                     default:
-                        await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);
+                        await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken);
                         break;
                 }
 
-                await iprot.ReadFieldEndAsync(cancellationToken);
+                await inputProtocol.ReadFieldEndAsync(cancellationToken);
             }
 
-            await iprot.ReadStructEndAsync(cancellationToken);
+            await inputProtocol.ReadStructEndAsync(cancellationToken);
 
             return new TApplicationException(type, message);
         }
 
-        public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)
+        public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken)
         {
             if (cancellationToken.IsCancellationRequested)
             {
@@ -123,27 +124,27 @@
             var struc = new TStruct(structApplicationExceptionName);
             var field = new TField();
 
-            await oprot.WriteStructBeginAsync(struc, cancellationToken);
+            await outputProtocol.WriteStructBeginAsync(struc, cancellationToken);
 
             if (!string.IsNullOrEmpty(Message))
             {
                 field.Name = messageTypeFieldName;
                 field.Type = TType.String;
                 field.ID = MessageTypeFieldId;
-                await oprot.WriteFieldBeginAsync(field, cancellationToken);
-                await oprot.WriteStringAsync(Message, cancellationToken);
-                await oprot.WriteFieldEndAsync(cancellationToken);
+                await outputProtocol.WriteFieldBeginAsync(field, cancellationToken);
+                await outputProtocol.WriteStringAsync(Message, cancellationToken);
+                await outputProtocol.WriteFieldEndAsync(cancellationToken);
             }
 
             field.Name = exTypeFieldName;
             field.Type = TType.I32;
             field.ID = ExTypeFieldId;
 
-            await oprot.WriteFieldBeginAsync(field, cancellationToken);
-            await oprot.WriteI32Async((int) Type, cancellationToken);
-            await oprot.WriteFieldEndAsync(cancellationToken);
-            await oprot.WriteFieldStopAsync(cancellationToken);
-            await oprot.WriteStructEndAsync(cancellationToken);
+            await outputProtocol.WriteFieldBeginAsync(field, cancellationToken);
+            await outputProtocol.WriteI32Async((int) Type, cancellationToken);
+            await outputProtocol.WriteFieldEndAsync(cancellationToken);
+            await outputProtocol.WriteFieldStopAsync(cancellationToken);
+            await outputProtocol.WriteStructEndAsync(cancellationToken);
         }
     }
 }
\ No newline at end of file
diff --git a/lib/netcore/Thrift/TBaseClient.cs b/lib/netcore/Thrift/TBaseClient.cs
index ca403e5..e019251 100644
--- a/lib/netcore/Thrift/TBaseClient.cs
+++ b/lib/netcore/Thrift/TBaseClient.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -16,14 +16,13 @@
 // under the License.
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Thrift.Protocols;
 
 namespace Thrift
 {
+    // ReSharper disable once InconsistentNaming
     /// <summary>
     ///     TBaseClient.
     ///     Base client for generated clients.
@@ -39,18 +38,8 @@
 
         protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol)
         {
-            if (inputProtocol == null)
-            {
-                throw new ArgumentNullException(nameof(inputProtocol));
-            }
-
-            if (outputProtocol == null)
-            {
-                throw new ArgumentNullException(nameof(outputProtocol));
-            }
-
-            _inputProtocol = inputProtocol;
-            _outputProtocol = outputProtocol;
+            _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol));
+            _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol));
         }
 
         public TProtocol InputProtocol => _inputProtocol;
diff --git a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
index 86eb735..761f1ac 100644
--- a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -34,17 +34,12 @@
         //TODO: should support only specified input transport?
         public TBufferedClientTransport(TClientTransport transport, int bufSize = 1024)
         {
-            if (transport == null)
-            {
-                throw new ArgumentNullException(nameof(transport));
-            }
-
             if (bufSize <= 0)
             {
                 throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number.");
             }
 
-            _transport = transport;
+            _transport = transport ?? throw new ArgumentNullException(nameof(transport));
             _bufSize = bufSize;
         }
 
@@ -200,8 +195,9 @@
             {
                 if (disposing)
                 {
-                    _inputBuffer.Dispose();
-                    _outputBuffer.Dispose();
+                    _inputBuffer?.Dispose();
+                    _outputBuffer?.Dispose();
+                    _transport?.Dispose();
                 }
             }
             _isDisposed = true;
diff --git a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
index f54a42a..d11bb95 100644
--- a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -37,12 +37,7 @@
 
         public TFramedClientTransport(TClientTransport transport)
         {
-            if (transport == null)
-            {
-                throw new ArgumentNullException(nameof(transport));
-            }
-
-            _transport = transport;
+            _transport = transport ?? throw new ArgumentNullException(nameof(transport));
 
             InitWriteBuffer();
         }
@@ -195,8 +190,9 @@
             {
                 if (disposing)
                 {
-                    _readBuffer.Dispose();
-                    _writeBuffer.Dispose();
+                    _readBuffer?.Dispose();
+                    _writeBuffer?.Dispose();
+                    _transport?.Dispose();
                 }
             }
             _isDisposed = true;
diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
index bc36bb3..16754b2 100644
--- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs
@@ -16,11 +16,9 @@
 // under the License.
 
 using System;
-using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Net;
 using System.Net.Http;
 using System.Net.Http.Headers;
 using System.Security.Cryptography.X509Certificates;
@@ -198,7 +196,7 @@
                 {
                     throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString());
                 }
-                catch (WebException wx)
+                catch (HttpRequestException wx)
                 {
                     throw new TTransportException(TTransportException.ExceptionType.Unknown,
                         "Couldn't connect to server: " + wx);
diff --git a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
index a44efe6..e769d14 100644
--- a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs
@@ -30,12 +30,7 @@
 
         public TSocketClientTransport(TcpClient client)
         {
-            if (client == null)
-            {
-                throw new ArgumentNullException(nameof(client));
-            }
-
-            TcpClient = client;
+            TcpClient = client ?? throw new ArgumentNullException(nameof(client));
 
             if (IsOpen)
             {
diff --git a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
index a21977b..c8be4ed 100644
--- a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -57,7 +57,7 @@
             if (isServer && certificate == null)
             {
                 throw new ArgumentException("TTlsSocketClientTransport needs certificate to be used for server",
-                    "certificate");
+                    nameof(certificate));
             }
 
             if (IsOpen)
@@ -204,7 +204,8 @@
                         ? new X509CertificateCollection {_certificate}
                         : new X509CertificateCollection();
 
-                    await _secureStream.AuthenticateAsClientAsync(_host.ToString(), certs, _sslProtocols, true);
+                    var targetHost = _host.ToString();
+                    await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true);
                 }
             }
             catch (Exception)
diff --git a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs b/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
index 6073741..032063a 100644
--- a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs
@@ -53,29 +53,14 @@
         public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputProtocolFactory,
             ITProtocolFactory outputProtocolFactory, RequestDelegate next, ILoggerFactory loggerFactory)
         {
-            if (processor == null)
-            {
-                throw new ArgumentNullException(nameof(processor));
-            }
-
-            if (inputProtocolFactory == null)
-            {
-                throw new ArgumentNullException(nameof(inputProtocolFactory));
-            }
-
-            if (outputProtocolFactory == null)
-            {
-                throw new ArgumentNullException(nameof(outputProtocolFactory));
-            }
-
             if (loggerFactory == null)
             {
                 throw new ArgumentNullException(nameof(loggerFactory));
             }
 
-            Processor = processor;
-            InputProtocolFactory = inputProtocolFactory;
-            OutputProtocolFactory = outputProtocolFactory;
+            Processor = processor ?? throw new ArgumentNullException(nameof(processor));
+            InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory));
+            OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory));
 
             _next = next;
             _logger = loggerFactory.CreateLogger<THttpServerTransport>();
diff --git a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs b/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
index 01195d4..186786e 100644
--- a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
diff --git a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
index af154ef..3a9d8a1 100644
--- a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs
@@ -30,6 +30,7 @@
         private readonly int _clientTimeout;
         private readonly int _port;
         private readonly bool _useBufferedSockets;
+        private readonly bool _useFramedTransport;
         private TcpListener _server;
 
         public TServerSocketTransport(TcpListener listener)
@@ -53,11 +54,17 @@
         {
         }
 
-        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets)
+        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets):
+            this(port, clientTimeout, useBufferedSockets, false)
+        {
+        }
+        
+        public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport)
         {
             _port = port;
             _clientTimeout = clientTimeout;
             _useBufferedSockets = useBufferedSockets;
+            _useFramedTransport = useFramedTransport;
             try
             {
                 // Make server socket
@@ -106,7 +113,7 @@
 
             try
             {
-                TSocketClientTransport tSocketTransport = null;
+                TClientTransport tSocketTransport = null;
                 var tcpClient = await _server.AcceptTcpClientAsync();
 
                 try
@@ -118,7 +125,12 @@
 
                     if (_useBufferedSockets)
                     {
-                        return new TBufferedClientTransport(tSocketTransport);
+                        tSocketTransport = new TBufferedClientTransport(tSocketTransport);
+                    }
+
+                    if (_useFramedTransport)
+                    {
+                        tSocketTransport = new TFramedClientTransport(tSocketTransport);
                     }
 
                     return tSocketTransport;
diff --git a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
index 49abdac..759feed 100644
--- a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
+++ b/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs
@@ -37,6 +37,7 @@
         private readonly X509Certificate2 _serverCertificate;
         private readonly SslProtocols _sslProtocols;
         private readonly bool _useBufferedSockets;
+        private readonly bool _useFramedTransport;
         private TcpListener _server;
 
         public TTlsServerSocketTransport(int port, X509Certificate2 certificate)
@@ -50,6 +51,19 @@
             X509Certificate2 certificate,
             RemoteCertificateValidationCallback clientCertValidator = null,
             LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
+            SslProtocols sslProtocols = SslProtocols.Tls12) 
+            : this(port, useBufferedSockets, false, certificate,
+                clientCertValidator, localCertificateSelectionCallback, sslProtocols)
+        {
+        }
+        
+        public TTlsServerSocketTransport(
+            int port,
+            bool useBufferedSockets,
+            bool useFramedTransport,
+            X509Certificate2 certificate,
+            RemoteCertificateValidationCallback clientCertValidator = null,
+            LocalCertificateSelectionCallback localCertificateSelectionCallback = null,
             SslProtocols sslProtocols = SslProtocols.Tls12)
         {
             if (!certificate.HasPrivateKey)
@@ -61,6 +75,7 @@
             _port = port;
             _serverCertificate = certificate;
             _useBufferedSockets = useBufferedSockets;
+            _useFramedTransport = useFramedTransport;
             _clientCertValidator = clientCertValidator;
             _localCertificateSelectionCallback = localCertificateSelectionCallback;
             _sslProtocols = sslProtocols;
@@ -122,13 +137,19 @@
 
                 await tTlsSocket.SetupTlsAsync();
 
+                TClientTransport trans = tTlsSocket;
+                
                 if (_useBufferedSockets)
                 {
-                    var trans = new TBufferedClientTransport(tTlsSocket);
-                    return trans;
+                    trans = new TBufferedClientTransport(trans);
                 }
 
-                return tTlsSocket;
+                if (_useFramedTransport)
+                {
+                    trans = new TFramedClientTransport(trans);
+                }
+                
+                return trans;
             }
             catch (Exception ex)
             {
diff --git a/lib/netcore/Thrift/Transports/TClientTransport.cs b/lib/netcore/Thrift/Transports/TClientTransport.cs
index cee0a00..0dd96cb 100644
--- a/lib/netcore/Thrift/Transports/TClientTransport.cs
+++ b/lib/netcore/Thrift/Transports/TClientTransport.cs
@@ -1,4 +1,4 @@
-// Licensed to the Apache Software Foundation(ASF) under one
+// 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
@@ -26,6 +26,7 @@
     // ReSharper disable once InconsistentNaming
     public abstract class TClientTransport : IDisposable
     {
+        //TODO: think how to avoid peek byte
         private readonly byte[] _peekBuffer = new byte[1];
         private bool _hasPeekByte;
         public abstract bool IsOpen { get; }
diff --git a/lib/netcore/Thrift/Transports/TServerTransport.cs b/lib/netcore/Thrift/Transports/TServerTransport.cs
index d49feb6..0d45a55 100644
--- a/lib/netcore/Thrift/Transports/TServerTransport.cs
+++ b/lib/netcore/Thrift/Transports/TServerTransport.cs
@@ -45,7 +45,7 @@
 
             if (transport == null)
             {
-                throw new TTransportException("AcceptAsync() should not return null");
+                throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null");
             }
 
             return transport;
diff --git a/lib/netcore/build.cmd b/lib/netcore/build.cmd
new file mode 100644
index 0000000..863c4b4
--- /dev/null
+++ b/lib/netcore/build.cmd
@@ -0,0 +1,27 @@
+@echo off
+rem /*
+rem  * Licensed to the Apache Software Foundation (ASF) under one
+rem  * or more contributor license agreements. See the NOTICE file
+rem  * distributed with this work for additional information
+rem  * regarding copyright ownership. The ASF licenses this file
+rem  * to you under the Apache License, Version 2.0 (the
+rem  * "License"); you may not use this file except in compliance
+rem  * with the License. You may obtain a copy of the License at
+rem  *
+rem  *   http://www.apache.org/licenses/LICENSE-2.0
+rem  *
+rem  * Unless required by applicable law or agreed to in writing,
+rem  * software distributed under the License is distributed on an
+rem  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem  * KIND, either express or implied. See the License for the
+rem  * specific language governing permissions and limitations
+rem  * under the License.
+rem  */
+
+setlocal
+
+thrift -version
+dotnet --info
+dotnet build 
+
+:eof
diff --git a/lib/netcore/build.sh b/lib/netcore/build.sh
new file mode 100644
index 0000000..ae18bce
--- /dev/null
+++ b/lib/netcore/build.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+#exit if any command fails
+#set -e
+
+thrift --version
+dotnet --info
+dotnet build 
+
+#revision=${TRAVIS_JOB_ID:=1}  
+#revision=$(printf "%04d" $revision) 
+
+#dotnet pack ./src/PROJECT_NAME -c Release -o ./artifacts --version-suffix=$revision  
diff --git a/lib/netcore/runtests.cmd b/lib/netcore/runtests.cmd
new file mode 100644
index 0000000..5114bc5
--- /dev/null
+++ b/lib/netcore/runtests.cmd
@@ -0,0 +1,28 @@
+@echo off
+rem /*
+rem  * Licensed to the Apache Software Foundation (ASF) under one
+rem  * or more contributor license agreements. See the NOTICE file
+rem  * distributed with this work for additional information
+rem  * regarding copyright ownership. The ASF licenses this file
+rem  * to you under the Apache License, Version 2.0 (the
+rem  * "License"); you may not use this file except in compliance
+rem  * with the License. You may obtain a copy of the License at
+rem  *
+rem  *   http://www.apache.org/licenses/LICENSE-2.0
+rem  *
+rem  * Unless required by applicable law or agreed to in writing,
+rem  * software distributed under the License is distributed on an
+rem  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem  * KIND, either express or implied. See the License for the
+rem  * specific language governing permissions and limitations
+rem  * under the License.
+rem  */
+setlocal
+
+thrift -version
+dotnet --info
+
+dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj
+dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj
+
+:eof
diff --git a/lib/netcore/runtests.sh b/lib/netcore/runtests.sh
new file mode 100644
index 0000000..a26cc36
--- /dev/null
+++ b/lib/netcore/runtests.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+#
+# 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.
+#
+
+thrift -version
+dotnet --info
+
+dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj
+dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj
\ No newline at end of file