/// <summary> /// 追加一个新的数据段 /// </summary> /// <param name="args">数据段接受参数</param> public void Append(SegmentReceiveEventArgs args) { lock (_lockObj) { _container.AppendNetworkData(args); MessageIdentity identity; if (!_container.TryReadMessageIdentity(out identity)) { _container.ResetOffset(); return; } _container.ResetOffset(); Type msgType = _protocolStack.GetMessageType(identity.Command, false); if (msgType == null) { _tracing.Error("#Type of Thrift message has no any registered .NET type. #Type: {0}, seqID={1}, data: \r\n{2}", identity.Command, identity.SequenceId, _container.Dump()); } else { try { ThriftMessage msg; if (ThriftObjectEngine.TryGetObject(msgType, _container, out msg) != GetObjectResultTypes.Succeed) { return; } _container.UpdateOffset(); OnParseSucceed(new LightSingleArgEventArgs <List <ThriftMessage> >(new List <ThriftMessage> { msg })); } catch (Exception ex) { _tracing.Error(ex, null); } } } }
/// <summary> /// 将一个元数据转换为特定类型的对象 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="target">特定的对象</param> /// <param name="container">网络数据容器</param> /// <param name="value">如果解析成功, 则此字段为解析成功后的值</param> /// <param name="isInnerObject"> /// 是否为内部对象 /// <para>* 如果此值被设置为false(默认值), 则会对当前类型尝试解析MessageIdentity字段</para> /// </param> /// <returns>返回一个解析后的状态</returns> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="Exception">转换失败</exception> public static GetObjectResultTypes TryGetObject <T>(Type target, INetworkDataContainer container, out T value, bool isInnerObject = false) { value = default(T); if (target == null) { throw new ArgumentNullException("target"); } if (container == null) { throw new ArgumentNullException("container"); } Dictionary <short, GetObjectAnalyseResult> result = Analyser.GetObjectAnalyser.Analyse(target); if (result == null) { return(GetObjectResultTypes.UnknownObjectType); } GetObjectResultTypes tmpFieldParsingResult; //create instance for new obj. Object instance = Activator.CreateInstance(target); ThriftObject thriftObject = instance as ThriftObject; if (thriftObject == null) { throw new Exception("Cannot convert target object to Intellect Object! #type: " + target.FullName); } #region Data Parsing. GetObjectAnalyseResult analyzeResult; if (!isInnerObject) { #region Message Identity. if (!result.TryGetValue(-1, out analyzeResult)) { throw new Exception("#Lost Thrift protocol object processor which it can handles type of MessageIdentity"); } if (analyzeResult.HasCacheFinished) { if ((tmpFieldParsingResult = analyzeResult.CacheProcess(instance, analyzeResult, container)) != GetObjectResultTypes.Succeed) { container.ResetOffset(); return(tmpFieldParsingResult); } } else { IThriftTypeProcessor processor = ThriftTypeProcessorMapping.Instance.GetProcessor(analyzeResult.Property.PropertyType); if (processor == null) { throw new Exception("#Lost Thrift protocol object processor which it can handles type of MessageIdentity"); } analyzeResult.CacheProcess = processor.Process; analyzeResult.HasEnoughData = processor.HasEnoughData; analyzeResult.HasCacheFinished = true; if ((tmpFieldParsingResult = analyzeResult.CacheProcess(instance, analyzeResult, container)) != GetObjectResultTypes.Succeed) { container.ResetOffset(); return(tmpFieldParsingResult); } } #endregion } while (true) { byte pType; //get property type. if (!container.TryReadByte(out pType)) { container.ResetOffset(); return(GetObjectResultTypes.NotEnoughData); } PropertyTypes propertyType = (PropertyTypes)pType; //succeed parsing binary data to a Thrift protocol object by finding Thrift protocol's STOP flag. if (propertyType == PropertyTypes.Stop) { value = (T)instance; return(GetObjectResultTypes.Succeed); } //get id. short id; if (!container.TryReadInt16(out id)) { container.ResetOffset(); return(GetObjectResultTypes.NotEnoughData); } id = id.ToLittleEndian(); //get analyze result. if (!result.TryGetValue(id, out analyzeResult)) { throw new Exception(string.Format("Illegal data contract, non-exists id! #id: {0} \r\n#Formatted MSG info: {1}, data: \r\n{2}", id, instance, container.Dump())); } //set current property value to the target object. if ((tmpFieldParsingResult = InstanceHelper.SetInstance(thriftObject, analyzeResult, container)) != GetObjectResultTypes.Succeed) { container.ResetOffset(); return(tmpFieldParsingResult); } } #endregion }