/// <summary> /// ע��һ��ThriftЭ�����ʹ����� /// <para>* ��������͵Ĵ������Ѿ����ڣ�������滻������</para> /// </summary> /// <param name="processor">ThriftЭ�����ʹ�����</param> public void Regist(IThriftTypeProcessor processor) { if (processor == null) return; try { if (_processor.ContainsKey(processor.SupportedType)) { _processor[processor.SupportedType] = processor; return; } _processor.Add(processor.SupportedType, processor); } catch (Exception ex) { _tracing.Error(ex, null); } }
/// <summary> /// 注册一个Thrift协议类型处理器 /// <para>* 如果该类型的处理器已经存在,则进行替换操作。</para> /// </summary> /// <param name="processor">Thrift协议类型处理器</param> public void Regist(IThriftTypeProcessor processor) { if (processor == null) { return; } try { if (_processor.ContainsKey(processor.SupportedType)) { _processor[processor.SupportedType] = processor; return; } _processor.Add(processor.SupportedType, processor); } catch (Exception ex) { _tracing.Error(ex, null); } }
/// <summary> /// 将一个智能对象转换为二进制元数据 /// </summary> /// <param name="obj">智能对象</param> /// <param name="proxy">内存段代理器</param> /// <returns>返回当前已经被序列化对象的总体长度</returns> internal static void ToBytes(IThriftObject obj, IMemorySegmentProxy proxy) { //获取智能对象中的智能属性,并按照Id来排序 ToBytesAnalyseResult[] properties = Analyser.ToBytesAnalyser.Analyse(obj); if (properties.Length == 0) { return; } for (int l = 0; l < properties.Length; l++) { ToBytesAnalyseResult property = properties[l]; //先检查完全缓存机制 if (property.HasCacheFinished) { property.CacheProcess(proxy, property.Attribute, property, obj, false, false); continue; } #region 普通类型判断 IThriftTypeProcessor intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(property.Property.PropertyType); if (intellectTypeProcessor != null) { //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; property.CacheProcess = processor.Process; property.CacheProcess(proxy, property.Attribute, property, obj, false, false); property.HasCacheFinished = true; continue; } #endregion #region 枚举类型判断 //枚举类型 if (property.Property.PropertyType.IsEnum) { //获取枚举类型 Type enumType = Enum.GetUnderlyingType(property.Property.PropertyType); intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(enumType); if (intellectTypeProcessor == null) { throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, property.Property.PropertyType)); } //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; property.CacheProcess = processor.Process; property.CacheProcess(proxy, property.Attribute, property, obj, false, false); property.HasCacheFinished = true; continue; } #endregion #region 可空类型判断 Type innerType; if ((innerType = Nullable.GetUnderlyingType(property.Property.PropertyType)) != null) { intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(innerType); if (intellectTypeProcessor != null) { //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; property.CacheProcess = delegate(IMemorySegmentProxy innerProxy, ThriftPropertyAttribute innerAttribute, ToBytesAnalyseResult innerAnalyseResult, object innerTarget, bool innerIsArrayElement, bool innerNullable) { processor.Process(innerProxy, innerAttribute, innerAnalyseResult, innerTarget, innerIsArrayElement, true); }; property.CacheProcess(proxy, property.Attribute, property, obj, false, true); property.HasCacheFinished = true; continue; } throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, property.Property.PropertyType)); } #endregion #region Thrift Object类型判断 if (property.Property.PropertyType.GetInterface(Consts.ThriftObjectFullName) != null) { //添加热缓存 property.CacheProcess = delegate(IMemorySegmentProxy innerProxy, ThriftPropertyAttribute innerAttribute, ToBytesAnalyseResult innerAnalyseResult, object innerTarget, bool innerIsArrayElement, bool innerNullable) { IThriftObject innerIntellectObj = innerAnalyseResult.GetValue <IThriftObject>(innerTarget); if (innerIntellectObj == null) { return; } innerProxy.WriteByte((byte)innerAttribute.Id); MemoryPosition startPos = innerProxy.GetPosition(); innerProxy.Skip(4); ToBytes(innerIntellectObj, innerProxy); MemoryPosition endPos = innerProxy.GetPosition(); innerProxy.WriteBackInt32(startPos, MemoryPosition.CalcLength(innerProxy.SegmentCount, startPos, endPos) - 4); }; property.CacheProcess(proxy, property.Attribute, property, obj, false, false); property.HasCacheFinished = true; continue; } #endregion #region 数组的判断 if (property.Property.PropertyType.IsArray) { if (!property.Property.PropertyType.HasElementType) { throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, property.Property.PropertyType)); } Type elementType = property.Property.PropertyType.GetElementType(); VT vt = FixedTypeManager.IsVT(elementType); //special optimize. IThriftTypeProcessor arrayProcessor = ArrayTypeProcessorMapping.Instance.GetProcessor(property.Property.PropertyType); if (arrayProcessor != null) { property.CacheProcess = arrayProcessor.Process; } //is VT, but cannot find special processor. else if (vt != null) { throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, property.Property.PropertyType)); } else if (elementType.IsSubclassOf(typeof(ThriftObject))) { //Add hot cache. property.CacheProcess = delegate(IMemorySegmentProxy innerProxy, ThriftPropertyAttribute innerAttribute, ToBytesAnalyseResult innerAnalyseResult, object innerTarget, bool innerIsArrayElement, bool innerNullable) { IThriftObject[] array = innerAnalyseResult.GetValue <IThriftObject[]>(innerTarget); if (array == null) { if (innerAttribute.Optional) { return; } throw new PropertyNullValueException(string.Format(ExceptionMessage.EX_PROPERTY_VALUE, innerAttribute.Id, innerAnalyseResult.Property.Name, innerAnalyseResult.Property.PropertyType)); } //property type innerProxy.WriteSByte((sbyte)innerAttribute.PropertyType); innerProxy.WriteInt16(((short)innerAttribute.Id).ToBigEndian()); //element type(1) + array length(4) innerProxy.WriteSByte((sbyte)PropertyTypes.Struct); innerProxy.WriteInt32(array.Length.ToBigEndian()); for (int i = 0; i < array.Length; i++) { IThriftObject element = array[i]; ToBytes(element, innerProxy); //end flag of Thrift protocol object. innerProxy.WriteSByte(0x00); } }; } else { intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(elementType); if (intellectTypeProcessor == null) { throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, elementType)); } //Add hot cache. IThriftTypeProcessor processor = intellectTypeProcessor; property.CacheProcess = delegate(IMemorySegmentProxy innerProxy, ThriftPropertyAttribute innerAttribute, ToBytesAnalyseResult innerAnalyseResult, object innerTarget, bool innerIsArrayElement, bool innerNullable) { Array array = innerAnalyseResult.GetValue <Array>(innerTarget); if (array == null) { if (innerAttribute.Optional) { return; } throw new PropertyNullValueException(string.Format(ExceptionMessage.EX_PROPERTY_VALUE, innerAttribute.Id, innerAnalyseResult.Property.Name, innerAnalyseResult.Property.PropertyType)); } //id(1) + total length(4) + rank(4) innerProxy.WriteByte((byte)innerAttribute.Id); MemoryPosition startPosition = innerProxy.GetPosition(); innerProxy.Skip(4); innerProxy.WriteInt32(array.Length); for (int i = 0; i < array.Length; i++) { object element = array.GetValue(i); if (element == null) { innerProxy.WriteUInt16(0); } else { MemoryPosition innerStartObjPosition = innerProxy.GetPosition(); innerProxy.Skip(Size.UInt16); processor.Process(innerProxy, innerAttribute, innerAnalyseResult, element, true); MemoryPosition innerEndObjPosition = innerProxy.GetPosition(); innerProxy.WriteBackUInt16(innerStartObjPosition, (ushort)(MemoryPosition.CalcLength(innerProxy.SegmentCount, innerStartObjPosition, innerEndObjPosition) - 2)); } } MemoryPosition endPosition = innerProxy.GetPosition(); innerProxy.WriteBackInt32(startPosition, MemoryPosition.CalcLength(innerProxy.SegmentCount, startPosition, endPosition) - 4); }; } property.CacheProcess(proxy, property.Attribute, property, obj, false, false); property.HasCacheFinished = true; continue; } #endregion throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, property.Attribute.Id, property.Property.Name, property.Property.PropertyType)); } }
/// <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 }
/// <summary> /// 设置字段实例 /// </summary> /// <param name="instance">对象实例</param> /// <param name="analyseResult">字段临时解析结构</param> /// <param name="container">网络数据容器</param> public static GetObjectResultTypes SetInstance(object instance, GetObjectAnalyseResult analyseResult, INetworkDataContainer container) { GetObjectAnalyseResult analyze = analyseResult; //热处理判断 if (analyze.HasCacheFinished) { return(analyze.CacheProcess(instance, analyseResult, container)); } #region 普通类型判断 IThriftTypeProcessor intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(analyze.Property.PropertyType); if (intellectTypeProcessor != null) { //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; analyze.CacheProcess = processor.Process; analyze.HasEnoughData = processor.HasEnoughData; analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container)); } #endregion #region 枚举类型判断 //枚举类型 if (analyze.Property.PropertyType.IsEnum) { Type enumType = Enum.GetUnderlyingType(analyze.Property.PropertyType); intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(enumType); if (intellectTypeProcessor == null) { throw new Exception("Cannot support this enum type! #type: " + analyze.Property.PropertyType); } //添加热处理 IThriftTypeProcessor processor = intellectTypeProcessor; analyze.CacheProcess = processor.Process; analyze.HasEnoughData = processor.HasEnoughData; analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container)); } #endregion #region 可空类型判断 Type innerType; if ((innerType = Nullable.GetUnderlyingType(analyze.Property.PropertyType)) != null) { intellectTypeProcessor = ThriftTypeProcessorMapping.Instance.GetProcessor(innerType); if (intellectTypeProcessor != null) { //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; analyze.CacheProcess = processor.Process; analyze.HasEnoughData = processor.HasEnoughData; analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container)); } throw new Exception("Cannot find compatible processor, #type: " + analyze.Property.PropertyType); } #endregion #region Thrift类型的判断 //Thrift对象的判断 if (analyze.Property.PropertyType.IsClass && analyze.Property.PropertyType.GetInterface(Consts.ThriftObjectFullName) != null) { //添加热缓存 analyze.CacheProcess = delegate(object innerInstance, GetObjectAnalyseResult innerAnalyseResult, INetworkDataContainer innerContainer) { GetObjectResultTypes r; ThriftObject tobj; if ((r = ThriftObjectEngine.TryGetObject(innerAnalyseResult.Property.PropertyType, innerContainer, out tobj, true)) != GetObjectResultTypes.Succeed) { return(r); } innerAnalyseResult.SetValue(innerInstance, tobj); return(GetObjectResultTypes.Succeed); }; analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container));; } #endregion #region 数组的判断 if (analyze.Property.PropertyType.IsArray) { Type elementType = analyze.Property.PropertyType.GetElementType(); intellectTypeProcessor = ArrayTypeProcessorMapping.Instance.GetProcessor(analyze.Property.PropertyType); if (intellectTypeProcessor != null) { //添加热缓存 IThriftTypeProcessor processor = intellectTypeProcessor; analyze.HasEnoughData = processor.HasEnoughData; analyze.CacheProcess = processor.Process; analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container)); } if (elementType.IsSubclassOf(typeof(ThriftObject))) { #region IntellectObject type array processor. //add HOT cache. analyze.CacheProcess = delegate(object innerInstance, GetObjectAnalyseResult innerAnalyseResult, INetworkDataContainer innerContainer) { if (!innerContainer.CheckEnoughSize(5)) { return(GetObjectResultTypes.NotEnoughData); } byte tmpData; int arrLen; if (!innerContainer.TryReadByte(out tmpData)) { return(GetObjectResultTypes.NotEnoughData); } PropertyTypes arrElementType = (PropertyTypes)tmpData; if (!innerContainer.TryReadInt32(out arrLen)) { return(GetObjectResultTypes.NotEnoughData); } arrLen = arrLen.ToLittleEndian(); Func <int, ThriftObject[]> func = ThriftObjectArrayHelper.GetFunc <ThriftObject>(analyze.Property.PropertyType); ThriftObject[] array = func(arrLen); for (int i = 0; i < arrLen; i++) { GetObjectResultTypes r; ThriftObject tobj; if ((r = ThriftObjectEngine.TryGetObject(innerAnalyseResult.Property.PropertyType.GetElementType(), innerContainer, out tobj, true)) != GetObjectResultTypes.Succeed) { return(r); } array[i] = tobj; } innerAnalyseResult.SetValue(innerInstance, array); return(GetObjectResultTypes.Succeed); }; #endregion } else { throw new NotSupportedException(string.Format(ExceptionMessage.EX_NOT_SUPPORTED_VALUE, analyseResult.Attribute.Id, analyseResult.Property.Name, analyseResult.Property.PropertyType)); } analyze.HasCacheFinished = true; return(analyze.CacheProcess(instance, analyseResult, container)); } #endregion throw new Exception("Cannot support this data type: " + analyze.Property.PropertyType); }