Beispiel #1
0
 static ThriftCloudEventV10 ThriftDeserializeV10(Stream stream)
 {
     using (var sr = new BinaryReader(stream, Encoding.UTF8, true))
     {
         return(ThriftSerializer.Deserialize <ThriftCloudEventV10>(sr.ReadBytes((int)stream.Length)));
     }
 }
Beispiel #2
0
        private static void StartThriftyServer(int port, string eurekaServer)
        {
            var factory = new LoggerFactory();

            factory.AddConsole(LogLevel.Debug);
            var serverConfig = new ThriftyServerOptions
            {
                QueueTimeout          = TimeSpan.FromMinutes(1),
                TaskExpirationTimeout = TimeSpan.FromMinutes(1)
            };


            var bootStrap = new ThriftyBootstrap(new object[] { new ScribeTest() },
                                                 serverConfig, new InstanceDescription("SampleApp", "TestApp122", PublicAddress), factory);

            bootStrap
            .SslConfig(new SslConfig
            {
                CertFile         = "server.pfx",
                CertPassword     = "******",
                CertFileProvider = new EmbeddedFileProvider(typeof(Program).GetTypeInfo().Assembly)
            })
            .AddService(typeof(IScribe), "0.0.1")
            .EurekaConfig(!String.IsNullOrWhiteSpace(eurekaServer), new EurekaClientConfig {
                EurekaServerServiceUrls = eurekaServer
            })
            .Bind(PublicAddress, port)
            .StartAsync();

            ThriftSerializer s = new ThriftSerializer(ThriftSerializer.SerializeProtocol.Binary);
        }
 /// <summary>
 /// Stores the result of the routine implementation to the output pipe.
 /// </summary>
 /// <param name="result">The result to store</param>
 private void SetResult(TR result)
 {
     Log(LogLevel.Debug, $"Storing Result {result.ToString()}");
     byte[] data = ThriftSerializer.Serialize(result);
     OutPipe.Store(data.Length);
     OutPipe.Store(data);
 }
Beispiel #4
0
 static void ThriftSerializeV11(ThriftCloudEventV11 ev, Stream stream)
 {
     using (var sw = new BinaryWriter(stream, Encoding.UTF8, true))
     {
         sw.Write(ThriftSerializer.Serialize(ev));
         sw.Flush();
     }
 }
Beispiel #5
0
 static ThriftCloudEventV11 ThriftDeserializeV11(Stream stream)
 {
     using (var sr = new BinaryReader(stream, Encoding.UTF8, true))
     {
         var result = ThriftSerializer.Deserialize <ThriftCloudEventV11>(sr.ReadBytes((int)stream.Length));
         result.AfterDeserialization();
         return(result);
     }
 }
Beispiel #6
0
        public void Set_Message()
        {
            var houseDto   = GetHouseDto();
            var bodyStream = ThriftSerializer.Serialize(houseDto);
            var message    = new Message(bodyStream);

            var thriftMessage = new ThriftMessage <HouseDto>(message);

            thriftMessage.BodyStream.ShouldNotBe(null);
        }
Beispiel #7
0
        public void TestSimpleBytes()
        {
            Simple simple1 = Simple.Create();

            byte[] buf1 = ThriftSerializer <Simple> .ToBytes(simple1);

            Simple simple2 = ThriftSerializer <Simple> .FromBytes(buf1);

            byte[] buf2 = ThriftSerializer <Simple> .ToBytes(simple2);

            Assert.Equal(buf1, buf2);
        }
Beispiel #8
0
        public void TestComplexBytes()
        {
            Complex complex1 = Complex.Create();

            byte[] buf1 = ThriftSerializer <Complex> .ToBytes(complex1);

            Complex complex2 = ThriftSerializer <Complex> .FromBytes(buf1);

            byte[] buf2 = ThriftSerializer <Complex> .ToBytes(complex2);

            Assert.Equal(buf1, buf2);
        }
Beispiel #9
0
        public void TestSturctWithAttributedConstuctor(String a, int b)
        {
            StructWithConstructor obj1 = new StructWithConstructor(a, b);

            ThriftSerializer ser = new ThriftSerializer();

            byte[] objectBytes         = ser.Serialize(obj1);
            StructWithConstructor obj2 = ser.Deserialize <StructWithConstructor>(objectBytes);

            Assert.False(Object.ReferenceEquals(obj1, obj2));
            Assert.Equal(obj1, obj2);
        }
Beispiel #10
0
        public void TestSimpleStruct()
        {
            SimpleStruct obj1 = CreateSimpleStructWithData();

            ThriftSerializer ser = new ThriftSerializer();

            byte[]       objectBytes = ser.Serialize(obj1);
            SimpleStruct obj2        = ser.Deserialize <SimpleStruct>(objectBytes);

            Assert.False(Object.ReferenceEquals(obj1, obj2));
            Assert.Equal(obj1, obj2);
        }
Beispiel #11
0
        public void TestSimpleStructArray()
        {
            var obj1 = CreateSimpleStructWithData();
            var obj2 = CreateSimpleStructWithData();

            var ser = new ThriftSerializer();

            byte[] objectBytes = ser.Serialize(new[] { obj1, obj2 });
            var    objs        = ser.Deserialize <SimpleStruct[]>(objectBytes);

            Assert.False(Object.ReferenceEquals(objs[0], obj1));
            Assert.False(Object.ReferenceEquals(objs[1], obj2));
            Assert.Equal(objs[0], obj1);
            Assert.Equal(objs[1], obj2);
        }
Beispiel #12
0
        public void Set_Message_And_Properties()
        {
            var houseDto   = GetHouseDto();
            var properties = new Dictionary <string, object>()
            {
                { "whatever", 1 }
            };
            string sessionId  = Guid.NewGuid().ToString();
            string label      = Guid.NewGuid().ToString();
            var    bodyStream = ThriftSerializer.Serialize(houseDto);
            var    message    = new Message(bodyStream, sessionId, label, properties);

            var thriftMessage = new ThriftMessage <HouseDto>(message);

            thriftMessage.Label.ShouldBe(label);
            thriftMessage.SessionId.ShouldBe(sessionId);
            thriftMessage.Label.ShouldBe(label);
            AssertProperties(thriftMessage, properties);
        }
Beispiel #13
0
        /// <inheritdoc />
        protected override void RunRoutine()
        {
            try
            {
                Log(LogLevel.Debug, "Try to receive result from ObjectiveRoutine");
                // Receive object from inPipe
                InPipe.ReadInt();
                T t = InPipe.Read(Activator.CreateInstance <T>());
                Log(LogLevel.Debug, $"Received from ObjectiveRoutine: {t.ToString()}");

                // Map function
                List <Tuple <string, TV> > tuples = Map(t);
                Log(LogLevel.Debug, $"Mapping done, created {tuples.Count} tuples");

                // Tell Receiver the number of tuples
                Log(LogLevel.Debug, "Storing number of tuples");
                OutPipe.Store(tuples.Count);

                // Store tuples to outPipe
                int i = 1;
                foreach (Tuple <string, TV> tuple in tuples)
                {
                    // Write key
                    Log(LogLevel.Debug, $"Write key {i}: {tuple.Item1}");
                    OutPipe.Store(tuple.Item1);
                    // Write value (size & data)
                    Log(LogLevel.Debug, $"Write value {i}: {tuple.Item2.ToString()}");
                    byte[] data = ThriftSerializer.Serialize(tuple.Item2);
                    OutPipe.Store(data.Length); // size
                    OutPipe.Store(data);
                    i++;
                }
            }
            catch (Exception e)
            {
                Log(LogLevel.Error, $"Error while running map routine: {e.Message}");
                throw new RoutineException(e);
            }
        }
Beispiel #14
0
            public ArraySegment <byte> TransformToArraySegment(T value)
            {
                var payload = ThriftSerializer.Serialize(value);

                return(new ArraySegment <byte>(payload));
            }
Beispiel #15
0
 public IEnumerable <T> RetrieveMessages <T>(int messageAmount, int timeout) where T : new()
 {
     return(_consumer.RetrieveMessages(messageAmount, timeout).Select(
                m => ThriftSerializer.Deserialize <T>(m.BodyStream)));
 }
Beispiel #16
0
        /// <summary>
        /// Invokes the specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns>IMessage.</returns>
        public override IMessage Invoke(IMessage message)
        {
            var mcm = (IMethodCallMessage)message;
            IMethodReturnMessage returnMessage = null;

            if (mcm.MethodBase.IsDefined(typeof(ThriftSOperationAttribute), false) == false)
            {
                throw new ThriftSException(string.Format("Missing ThriftSOperationAttribute in '{0}.{1}'.", this.ServiceName, mcm.MethodName));
            }

            object returnValue = null;

            var stopwatch = new Stopwatch();

            string invokeDesc = string.Format("调用{0}契约的{1}方法", this.ServiceName, mcm.MethodName);

            // 构造请求
            var srequest = new ThriftSRequest()
            {
                ServiceName = this.ServiceName,
                MethodName  = Utils.GetMethodName((MethodInfo)mcm.MethodBase),
                Headers     = new Dictionary <string, string>(),
                Parameters  = new List <ThriftSParameter>()
            };

            srequest.Uri            = string.Format("thrift://{0}:{1}/{2}/{3}", this.Host, this.Port, this.ServiceShortName, srequest.MethodName);
            srequest.Version        = Utils.Version;
            srequest.ClientPid      = this.ClientPid;
            srequest.ClientHostName = this.ClientHostName;
            srequest.ClientRuntime  = ".NET " + Environment.Version.ToString();

            try
            {
                // 计时开始
                stopwatch.Start();
                if (mcm.Args != null)
                {
                    for (var i = 0; i < mcm.Args.Length; i++)
                    {
                        var argument = mcm.Args[i];

                        ThriftSParameter parameter = null;
                        if (argument == null)
                        {
                            parameter = new ThriftSParameter()
                            {
                                Index       = (sbyte)i,
                                Name        = string.Empty,
                                Type        = string.Empty,
                                Compression = ThriftSCompression.None,
                                ContentType = ContentTypes.Binary,
                                HasValue    = false
                            };
                        }
                        else
                        {
                            parameter = new ThriftSParameter()
                            {
                                Index       = (sbyte)i,
                                Name        = string.Empty,
                                Type        = string.Empty,
                                Compression = ThriftSCompression.None,
                                ContentType = ContentTypes.Thrift,
                                HasValue    = true,
                                Value       = ThriftSerializer.Serialize(argument)
                            };
                        }

                        // 大于10K开启压缩
                        if (parameter.Value != null && parameter.Value.Length > 10 * 1024)
                        {
                            parameter.Value       = Utils.GzipCompress(parameter.Value);
                            parameter.Compression = ThriftSCompression.Gzip;
                        }

                        srequest.Parameters.Add(parameter);
                    }
                }

                ThriftSResponse sresponse = null;
                try
                {
                    var xpool = ConnectionPoolManager.GetPool(this.Host, this.Port, this.Timeout);
                    ThriftSConnection xconnection     = null;
                    TimeSpan          connectTookTime = TimeSpan.MinValue;
                    try
                    {
                        DateTime beginConnectTime = DateTime.Now;
                        xconnection     = xpool.Borrow();
                        connectTookTime = beginConnectTime - DateTime.Now;

                        if (string.IsNullOrEmpty(this.ClientIP))
                        {
                            this.ClientIP = xconnection.LocalAddress.ToString();
                        }

                        srequest.ClientIP = this.ClientIP;
                        sresponse         = xconnection.Client.Process(srequest);
                    }
                    catch (SocketException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        this.HandleException("SocketException", invokeDesc, srequest, exception);
                    }
                    catch (IOException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        var socketException = exception.InnerException as SocketException;
                        if (socketException != null)
                        {
                            this.HandleException("SocketException", invokeDesc, srequest, socketException);
                        }

                        this.HandleException("IOException", invokeDesc, srequest, exception);
                    }
                    catch (TTransportException exception)
                    {
                        xpool.ReportError(xconnection, exception);

                        // 5秒以内的timeout认为是服务器积极拒绝.
                        if (exception.Message.StartsWith("Connect timed out") &&
                            connectTookTime.TotalSeconds < 5)
                        {
                            // 处理异常
                            this.HandleException(
                                "TTransportException",
                                invokeDesc,
                                srequest,
                                new TTransportException(exception.Type, "Service unavailable."));
                        }
                        else
                        {
                            this.HandleException("TTransportException", invokeDesc, srequest, exception);
                        }
                    }
                    catch (TProtocolException exception)
                    {
                        xpool.ReportError(xconnection, exception);
                        this.HandleException("TProtocolException", invokeDesc, srequest, exception);
                    }
                    finally
                    {
                        // 内部Try可以更快的释放连接。
                        xpool.Release(xconnection);
                    }

                    // 非void且result非空
                    if (sresponse != null && sresponse.Result != null)
                    {
                        // 解压
                        if (sresponse.Result.Compression == ThriftSCompression.Gzip)
                        {
                            sresponse.Result.Data = Utils.GzipUnCompress(sresponse.Result.Data);
                        }

                        if (sresponse.Result.ContentType == ContentTypes.Thrift)
                        {
                            returnValue = ThriftSerializer.Deserialize(
                                ((MethodInfo)mcm.MethodBase).ReturnType,
                                sresponse.Result.Data);
                        }
                        else
                        {
                            throw new NotSupportedException(string.Format("Not supported content type: {0}", sresponse.Result.ContentType));
                        }
                    }

                    returnMessage = new ReturnMessage(returnValue, null, 0, mcm.LogicalCallContext, mcm);
                }
                catch (TApplicationException tapplicationException)
                {
                    var info      = string.Format("tapplication exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(info + tapplicationException.Message, tapplicationException);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (BadRequestException badRequestException)
                {
                    var info      = string.Format("Bad request exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + badRequestException.ErrorMessage,
                        info + Environment.NewLine + badRequestException.ErrorMessage);

                    // 远端异常使用ReturnMessage包装
                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (InternalServerException internalServerException)
                {
                    var info      = string.Format("Server internal exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + internalServerException.ErrorMessage,
                        info + Environment.NewLine + internalServerException.ErrorDescription);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (InvocationException invocationException)
                {
                    var info      = string.Format("Server invocation exception on calling {0}. ", srequest.Uri);
                    var exception = new ThriftSException(
                        info + invocationException.ErrorMessage,
                        info + Environment.NewLine + invocationException.ErrorDescription);

                    returnMessage = new ReturnMessage(exception, mcm);
                }
                catch (Exception exception)
                {
                    this.HandleException("Exception", invokeDesc, srequest, exception);
                }
            }
            finally
            {
                stopwatch.Stop();
            }

            return(returnMessage);
        }
Beispiel #17
0
 public Task <String> CreateSharedResource <T>(String pId, String dataTypeId, T value) where T : TBase
 {
     byte[] data = ThriftSerializer.Serialize <T>(value);
     return(CreateSharedResource(pId, dataTypeId, data));
 }
Beispiel #18
0
 public T ExtractValueFromResource <T>(ResourceDTO resource) where T : TBase
 {
     return(ThriftSerializer.Deserialize <T>(resource.Data));
 }
Beispiel #19
0
        /// <summary>
        /// 请求处理
        /// </summary>
        /// <param name="request">request</param>
        /// <returns>response</returns>
        public ThriftSResponse Process(ThriftSRequest request)
        {
            if (request == null ||
                string.IsNullOrWhiteSpace(request.ServiceName) ||
                string.IsNullOrWhiteSpace(request.MethodName))
            {
                throw new BadRequestException(request, "The ServiceName or MethodName must be not null.");
            }

            if (LocalCache.ServiceDictionary.ContainsKey(request.ServiceName) == false)
            {
                throw new BadRequestException(request, "Service not found.");
            }

            if (LocalCache.ServiceDictionary[request.ServiceName].ContainsKey(request.MethodName) == false)
            {
                throw new BadRequestException(request, "Method not found.");
            }

            ThriftSEnvirnment.Logger.Debug("Accept request: {0}", request.Uri);

            var serviceMetadata = LocalCache.ServiceDictionary[request.ServiceName][request.MethodName];

            // 创建服务实例
            var service = Activator.CreateInstance(serviceMetadata.ServiceHandlerType);

            // 参数赋值
            var methodParameters = serviceMetadata.Method.GetParameters();
            var invokeParameters = new Dictionary <string, object>();

            for (var i = 0; i < methodParameters.Length; i++)
            {
                var parameter = methodParameters[i];

                // 在跨平台的时候服务端和客户端的参数名可能完全不一样,因此唯一依据是参数顺序,请求上下文的参数名以服务端为基准。
                request.Parameters[i].Name = parameter.Name;
                try
                {
                    ThriftSEnvirnment.Logger.Debug(string.Format(
                                                       new FileSizeFormatProvider(),
                                                       "Request parameter:{0}, ContentType:{1}, Compress:{2}, Length:{3:fs}",
                                                       parameter.Name,
                                                       request.Parameters[i].ContentType,
                                                       request.Parameters[i].Compression,
                                                       request.Parameters[i].HasValue ? request.Parameters[i].Value.Length : 0));

                    // 解压
                    if (request.Parameters[i].Compression == ThriftSCompression.Gzip)
                    {
                        request.Parameters[i].Value = Utils.GzipUnCompress(request.Parameters[i].Value);
                    }

                    if (request.Parameters[i].HasValue == false)
                    {
                        invokeParameters.Add(parameter.Name, null);
                    }
                    else
                    {
                        //if (request.Parameters[i].ContentType == ContentTypes.Protobuf)
                        //{
                        //    invokeParameters.Add(
                        //        parameter.Name,
                        //        Utils.DeserializeFromBytes(parameter.ParameterType, request.Parameters[i].Value));
                        //}
                        //else if (request.Parameters[i].ContentType == ContentTypes.Json)
                        //{
                        //    invokeParameters.Add(
                        //        parameter.Name,
                        //        Utils.DeserializeFromJson(parameter.ParameterType, request.Parameters[i].Value));
                        //}else
                        if (request.Parameters[i].ContentType == ContentTypes.Thrift)
                        {
                            invokeParameters.Add(
                                parameter.Name,
                                ThriftSerializer.Deserialize(parameter.ParameterType, request.Parameters[i].Value));
                        }
                        else
                        {
                            throw new NotSupportedException(string.Format("Not supported content type: {0}", request.Parameters[i].ContentType));
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new BadRequestException(
                              request,
                              string.Format("Parsing error on parameter '{0}'. {1}", parameter.Name, ex.Message));
                }
            }

            var    stopwatch = new Stopwatch();
            object result    = null;
            var    xresponse = new ThriftSResponse()
            {
                Headers = new Dictionary <string, string>()
            };

            xresponse.Version = Utils.Version;

            try
            {
                stopwatch.Start();

                try
                {
                    // 关联调用上下文
                    ThriftSContext.Current = new ThriftSContext()
                    {
                        Request = request
                    };

                    Func <object> action = () => serviceMetadata.Handle(service, invokeParameters.Values.ToArray());

                    if (serviceMetadata.Attribute.IsOneWay)
                    {
                        action.BeginInvoke(null, null);
                    }
                    else
                    {
                        result = action();
                    }

                    /*
                     * //异步调用,可以做oneway和timeout
                     * //Func<object> action = () =>
                     * //{
                     * //    return serviceMetadata.Handle(service, invokeParameters.Values.ToArray());
                     * //};
                     *
                     * //IAsyncResult asyncResult = action.BeginInvoke(null, null);
                     * //var isGetSignal = asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(60));
                     * //if (isGetSignal == false)
                     * //{
                     * //    throw new TimeoutException("Execution timeout.");
                     * //}
                     * //result = action.EndInvoke(asyncResult);
                     */
                }
                catch (Exception ex)
                {
                    throw new InvocationException()
                          {
                              Request          = request,
                              ErrorMessage     = ex.Message,
                              ErrorDescription = ex.ToString()
                          };
                }

                // 检查返回值
                if (serviceMetadata.Method.ReturnType != typeof(void))
                {
                    if (result != null)
                    {
                        //if (Utils.GetSerializerMode(result.GetType()) == SerializerMode.ProtoBuf)
                        //{
                        //    xresponse.Result = new ThriftSResult()
                        //    {
                        //        ContentType = ContentTypes.Protobuf,
                        //        Compression = ThriftSCompression.None,
                        //        Data = Utils.SerializeToBytes(result)
                        //    };
                        //}
                        //else if (Utils.GetSerializerMode(result.GetType()) == SerializerMode.Json)
                        //{
                        //    xresponse.Result = new ThriftSResult()
                        //    {
                        //        ContentType = ContentTypes.Json,
                        //        Compression = ThriftSCompression.None,
                        //        Data = Utils.SerializeToJson(result)
                        //    };
                        //}
                        //else
                        {
                            xresponse.Result = new ThriftSResult()
                            {
                                ContentType = ContentTypes.Thrift,
                                Compression = ThriftSCompression.None,
                                Data        = ThriftSerializer.Serialize(result)
                            };
                        }

                        // 大于10K开启压缩
                        if (xresponse.Result.Data.Length > 10 * 1024)
                        {
                            xresponse.Result.Data        = Utils.GzipCompress(xresponse.Result.Data);
                            xresponse.Result.Compression = ThriftSCompression.Gzip;
                        }

                        ThriftSEnvirnment.Logger.Debug(string.Format(
                                                           new FileSizeFormatProvider(),
                                                           "Render response. ContentType:{0}, Compress:{1}, Length:{2:fs}",
                                                           xresponse.Result.ContentType,
                                                           xresponse.Result.Compression,
                                                           xresponse.Result.Data.Length));
                    }
                }
            }
            catch (Exception ex)
            {
                if (ex is InvocationException)
                {
                    throw;
                }

                throw new InternalServerException()
                      {
                          Request          = request,
                          ErrorMessage     = ex.Message,
                          ErrorDescription = ex.ToString()
                      };
            }
            finally
            {
                stopwatch.Stop();

                ThriftSEnvirnment.Logger.Debug("Request end. Took: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
            }

            return(xresponse);
        }
Beispiel #20
0
        public void TestComplexStruct()
        {
            SimpleStruct obj1 = CreateSimpleStructWithData();

            ComplexStruct complex1 = new ComplexStruct();

            complex1.Simple = obj1;
            complex1.IEnumerableProperty = new float[] { 99.99F, 88.88F };
            complex1.IListProperty       = complex1.IEnumerableProperty.ToList();
            complex1.ISetProperty        = new HashSet <float> {
                55f, 66f
            };
            complex1.IDictionaryProperty = new Dictionary <float, String>
            {
                { 1f, "A" },
                { 2f, "B" }
            };
            complex1.DictionaryIntKeyProperty = new Dictionary <int, SimpleStruct>
            {
                { 1, new SimpleStruct {
                      StringProperty = "1Property"
                  } },
                { 2, new SimpleStruct {
                      StringProperty = "2Property"
                  } }
            };

            complex1.EnumArrayProperty      = new SimpleEnum[] { SimpleEnum.ValueTwo, SimpleEnum.ValueOne };
            complex1.EnumDictionaryProperty = new Dictionary <string, SimpleEnum>
            {
                { "d1Enum", SimpleEnum.ValueTwo },
                { "d2Enum", SimpleEnum.ValueOne }
            };

            complex1.EnumListProperty = new List <SimpleEnum>()
            {
                SimpleEnum.ValueTwo, SimpleEnum.ValueOne
            };
            complex1.EnumSetProperty = new HashSet <SimpleEnum> {
                SimpleEnum.ValueOne, SimpleEnum.ValueTwo
            };

            complex1.IntArrayProperty          = new int[] { 1, 2, 3, 4, 5 };
            complex1.SimpleDictionaryProperty1 = new Dictionary <int, float>
            {
                { 1, 3.33f }, { 2, 4.44f }
            };
            complex1.SimpleDictionaryProperty2 = new Dictionary <string, float>
            {
                { "a", 3.33f }, { "b", 4.44f }
            };
            complex1.StructListProperty = new List <SimpleStruct>
            {
                new SimpleStruct {
                    StringProperty = "listItem1"
                },
                new SimpleStruct {
                    StringProperty = "listItem2"
                }
            };
            complex1.StructSetProperty = new HashSet <SimpleStruct>
            {
                new SimpleStruct {
                    StringProperty = "setItem1"
                },
                new SimpleStruct {
                    StringProperty = "setItem2"
                }
            };

            complex1.StructArrayProperty = new SimpleStruct[]
            {
                new SimpleStruct {
                    StringProperty = "setItem1"
                },
                new SimpleStruct {
                    StringProperty = "setItem2"
                }
            };


            ThriftSerializer ser = new ThriftSerializer();

            byte[]        objectBytes = ser.Serialize(complex1);
            ComplexStruct complex2    = ser.Deserialize <ComplexStruct>(objectBytes);

            Assert.False(Object.ReferenceEquals(complex1, complex2));
            Assert.Equal(complex1.Simple, complex2.Simple);
            AssertEx.Equals(complex1.DictionaryIntKeyProperty, complex2.DictionaryIntKeyProperty);
            AssertEx.Equals(complex1.EnumArrayProperty, complex2.EnumArrayProperty);
            AssertEx.Equals(complex1.EnumDictionaryProperty, complex2.EnumDictionaryProperty);
            AssertEx.Equals(complex1.EnumListProperty, complex2.EnumListProperty);
            AssertEx.Equals(complex1.EnumSetProperty, complex2.EnumSetProperty);
            AssertEx.Equals(complex1.IntArrayProperty, complex2.IntArrayProperty);
            AssertEx.Equals(complex1.SimpleDictionaryProperty1, complex2.SimpleDictionaryProperty1);
            AssertEx.Equals(complex1.SimpleDictionaryProperty2, complex2.SimpleDictionaryProperty2);
            AssertEx.Equals(complex1.StructListProperty, complex2.StructListProperty);
            AssertEx.Equals(complex1.StructSetProperty, complex2.StructSetProperty);
            AssertEx.Equals(complex1.IEnumerableProperty, complex2.IEnumerableProperty);
            AssertEx.Equals(complex1.IListProperty, complex2.IListProperty);
            AssertEx.Equals(complex1.ISetProperty, complex2.ISetProperty);
            AssertEx.Equals(complex1.IDictionaryProperty, complex2.IDictionaryProperty);
            AssertEx.Equals(complex1.StructArrayProperty, complex2.StructArrayProperty);
        }