/// <summary> /// Gets the default TypeCoercion (and associated ThriftType) for the specified csharp type. /// </summary> /// <param name="type"></param> /// <returns></returns> public TypeCoercion GetDefaultCoercion(Type type) { TypeCoercion r = null; _coercions.TryGetValue(type, out r); return(r); }
protected override ThriftFieldMetadata BuildField(IEnumerable <FieldMetadata> input) { short id = -1; //IDictionary<String, String> idlAnnotations = null; String name = null; Requiredness requiredness = Requiredness.Unspecified; bool recursive = false; IThriftTypeReference thriftTypeReference = null; // process field injections and extractions List <IThriftInjection> injections = new List <IThriftInjection>(); IThriftExtraction extraction = null; foreach (FieldMetadata fieldMetadata in input) { id = fieldMetadata.Id; name = fieldMetadata.Name; recursive = fieldMetadata.IsRecursiveReference ?? false; requiredness = fieldMetadata.Requiredness; //idlAnnotations = fieldMetadata.getIdlAnnotations(); thriftTypeReference = this.Catalog.GetFieldThriftTypeReference(fieldMetadata); FieldInjection fieldInjection = fieldMetadata as FieldInjection; if (fieldInjection != null) { injections.Add(new ThriftFieldInjection(fieldInjection.Id, fieldInjection.Name, fieldInjection.Field, fieldInjection.Type)); } else if (fieldMetadata is ParameterInjection) { ParameterInjection parameterInjection = (ParameterInjection)fieldMetadata; injections.Add(new ThriftParameterInjection( parameterInjection.Id, parameterInjection.Name, parameterInjection.ParameterIndex, fieldMetadata.CSharpType )); } else if (fieldMetadata is FieldExtractor) { FieldExtractor fieldExtractor = (FieldExtractor)fieldMetadata; extraction = new ThriftFieldExtractor( fieldExtractor.Id, fieldExtractor.Name, fieldExtractor.Type, fieldExtractor.Field, fieldExtractor.CSharpType); } else if (fieldMetadata is MethodExtractor) { MethodExtractor methodExtractor = (MethodExtractor)fieldMetadata; extraction = new ThriftMethodExtractor( methodExtractor.Id, methodExtractor.Name, methodExtractor.Type, methodExtractor.Method, methodExtractor.CSharpType); } } // add type coercion TypeCoercion coercion = null; if (!thriftTypeReference.Recursive && thriftTypeReference.Get().IsCoerced) { coercion = this.Catalog.GetDefaultCoercion(thriftTypeReference.Get().CSharpType); } if (recursive && requiredness != Requiredness.Optional) { this.MetadataErrors.AddError($"Struct '{this.StructName}' field '{name}' is recursive but not marked optional"); } ThriftFieldMetadata thriftFieldMetadata = new ThriftFieldMetadata( id, recursive, requiredness, //idlAnnotations, thriftTypeReference, name, FieldKind.ThriftField, injections, extraction: extraction, coercion: coercion ); return(thriftFieldMetadata); }
//private IEnumerable<String> documentation; public ThriftFieldMetadata( short id, bool isRecursiveReference, Requiredness requiredness, //IEnumerable<KeyValuePair<String, String>> idlAnnotations, IThriftTypeReference thriftTypeReference, String name, FieldKind fieldKind, IEnumerable <IThriftInjection> injections = null, ThriftConstructorInjection constructorInjection = null, ThriftMethodInjection methodInjection = null, IThriftExtraction extraction = null, TypeCoercion coercion = null ) { Guard.ArgumentNotNull(thriftTypeReference, nameof(thriftTypeReference)); Guard.ArgumentNotNull(fieldKind, nameof(fieldKind)); Guard.ArgumentNullOrWhiteSpaceString(name, nameof(name)); Guard.ArgumentNotNull(thriftTypeReference, nameof(thriftTypeReference)); Guard.ArgumentNullOrWhiteSpaceString(name, nameof(name)); //Guard.ArgumentNotNull(constructorInjection, nameof(constructorInjection)); //Guard.ArgumentNotNull(methodInjection, nameof(methodInjection)); //Guard.ArgumentNotNull(extraction, nameof(extraction)); //Guard.ArgumentNotNull(coercion, nameof(coercion)); this.IsRecursiveReference = isRecursiveReference; this.Required = requiredness; this._thriftTypeReference = thriftTypeReference; this._fieldKind = fieldKind; this.Name = name; this.Injections = injections ?? Enumerable.Empty <IThriftInjection>(); this._constructorInjection = constructorInjection; this._methodInjection = methodInjection; this._extraction = extraction; this._coercion = coercion; switch (fieldKind) { case FieldKind.ThriftField: Guard.ArgumentCondition(id >= 0, "isLegacyId must be specified on fields with negative IDs", nameof(id)); break; case FieldKind.ThriftUnionId: Guard.ArgumentCondition(id == short.MinValue, "thrift union id must be short.MinValue", nameof(id)); break; } Guard.ArgumentCondition(injections.Any() || extraction != null || constructorInjection != null || methodInjection != null, "A thrift field must have an injection or extraction point"); this.Id = id; if (extraction != null) { if (extraction is ThriftFieldExtractor) { ThriftFieldExtractor e = (ThriftFieldExtractor)extraction; //this.documentation = ThriftCatalog.getThriftDocumentation(e.getField()); } else if (extraction != null && extraction is ThriftMethodExtractor) { ThriftMethodExtractor e = (ThriftMethodExtractor)extraction; //this.documentation = ThriftCatalog.getThriftDocumentation(e.getMethod()); } } //this.idlAnnotations = idlAnnotations; }
// This should ONLY be called from buildThriftType() private ThriftType BuildThriftTypeInternal(Type csharpType) { ThriftType manualType = null; Type rawType = csharpType; if (_manualTypes.TryGetValue(csharpType, out manualType)) { return(manualType); } if (typeof(bool).Equals(rawType)) { return(ThriftType.Bool); } if (typeof(byte).Equals(rawType)) { return(ThriftType.Byte); } if (typeof(short).Equals(rawType)) { return(ThriftType.I16); } if (typeof(int).Equals(rawType)) { return(ThriftType.I32); } if (typeof(long).Equals(rawType)) { return(ThriftType.I64); } if (typeof(double).Equals(rawType)) { return(ThriftType.Double); } if (typeof(float).Equals(rawType)) { return(ThriftType.Float); } if (typeof(String).Equals(rawType)) { return(ThriftType.String); } if (typeof(Guid).Equals(rawType)) { return(ThriftType.Guid); } if (typeof(DateTime).Equals(rawType)) { return(ThriftType.DateTime); } if (typeof(Decimal).Equals(rawType)) { return(ThriftType.Decimal); } if (typeof(byte[]).Equals(rawType)) { // byte[] is encoded as BINARY and requires a coersion return(ThriftType.Binary); } if (rawType.GetTypeInfo().IsEnum) { return(ThriftType.Enum(new ThriftEnumMetadata(rawType))); } var dicType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IDictionary <,>))); if (dicType != null) { var argTypes = dicType.GetTypeInfo().GetGenericArguments(); Type mapKeyType = argTypes[0]; Type mapValueType = argTypes[1]; return(ThriftType.Dictionary( GetMapKeyThriftTypeReference(mapKeyType), GetMapValueThriftTypeReference(mapValueType))); } if (rawType.IsArray) { var elementType = rawType.GetTypeInfo().GetElementType(); return(ThriftType.Array(GetCollectionElementThriftTypeReference(elementType))); } var setType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(ISet <>))); if (setType != null) { Type elementType = setType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.Set(GetCollectionElementThriftTypeReference(elementType))); } var listType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IList <>))); if (listType != null) { Type elementType = listType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.List(GetCollectionElementThriftTypeReference(elementType))); } var arrayType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IEnumerable <>))); if (arrayType != null) { Type elementType = arrayType.GetTypeInfo().GetGenericArguments().First(); return(ThriftType.Array(GetCollectionElementThriftTypeReference(elementType))); } // The void type is used by service methods and is encoded as an empty struct if (typeof(void).IsAssignableFrom(rawType) || typeof(Task).Equals(rawType)) { return(ThriftType.Void); } if (IsStructType(rawType)) { ThriftStructMetadata structMetadata = GetThriftStructMetadata(csharpType); // Unions are covered because a union looks like a struct with a single field. return(ThriftType.Struct(structMetadata)); } if (rawType.GetTypeInfo().IsGenericType&& rawType.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(Task <>))) { Type returnType = rawType.GetTypeInfo().GetGenericArguments().First(); // TODO: check that we aren't recursing through multiple futures // TODO: find a way to restrict this to return values only return(GetThriftType(returnType)); } // coerce the type if possible TypeCoercion coercion = null; if (_coercions.TryGetValue(csharpType, out coercion)) { return(coercion.ThriftType); } if (IsNullableEnum(rawType)) { coercion = _coercions.GetOrAdd(rawType, t => { ThriftEnumMetadata m = new ThriftEnumMetadata(t.GetTypeInfo().GetGenericArguments().First()); var tt = ThriftType.Enum(m, true); return(new TypeCoercion(tt)); }); return(coercion.ThriftType); } throw new ThriftyException($"Type can not be coerced to a Thrift type: {csharpType.FullName}"); }
public ThriftProtocolType GetThriftProtocolType(Type rawType) { if (typeof(bool).Equals(rawType)) { return(ThriftProtocolType.Bool); } if (typeof(byte).Equals(rawType)) { return(ThriftProtocolType.Byte); } if (typeof(short).Equals(rawType)) { return(ThriftProtocolType.I16); } if (typeof(int).Equals(rawType)) { return(ThriftProtocolType.I32); } if (typeof(long).Equals(rawType)) { return(ThriftProtocolType.I64); } if (typeof(double).Equals(rawType)) { return(ThriftProtocolType.Double); } if (typeof(float).Equals(rawType)) { return(ThriftProtocolType.Double); } if (typeof(String).Equals(rawType)) { return(ThriftProtocolType.String); } if (typeof(byte).Equals(rawType)) { return(ThriftProtocolType.Byte); } if (typeof(DateTime).Equals(rawType)) { return(ThriftProtocolType.I64); } if (typeof(Guid).Equals(rawType)) { return(ThriftProtocolType.String); } if (typeof(Decimal).Equals(rawType)) { return(ThriftProtocolType.String); } if (typeof(byte[]).Equals(rawType)) { return(ThriftProtocolType.Binary); } if (rawType.GetTypeInfo().IsEnum) { return(ThriftProtocolType.Enum); } var dicType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IDictionary <,>))); if (dicType != null) { return(ThriftProtocolType.Map); } //if (rawType.IsArray) //TODO: 这里应该判断基础类型,使用 Array 协议,不符合 thrift 标准 //{ // return ThriftProtocolType.List; //} var setType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(ISet <>))); if (setType != null) { return(ThriftProtocolType.Set); } var listType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IList <>))); if (listType != null) { return(ThriftProtocolType.List); } var arrayType = rawType.GetInterfaces().Concat(new Type[] { rawType }).FirstOrDefault(t => t.GetTypeInfo().IsGenericType&& t.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(IEnumerable <>))); if (arrayType != null) { return(ThriftProtocolType.List); } // The void type is used by service methods and is encoded as an empty struct if (typeof(void).IsAssignableFrom(rawType) || typeof(Task).Equals(rawType)) { return(ThriftProtocolType.Struct); } if (IsStructType(rawType)) { return(ThriftProtocolType.Struct); } if (rawType.GetTypeInfo().IsGenericType&& rawType.GetTypeInfo().GetGenericTypeDefinition().Equals(typeof(Task <>))) { Type returnType = rawType.GetTypeInfo().GetGenericArguments().First(); // TODO: check that we aren't recursing through multiple futures // TODO: find a way to restrict this to return values only return(this.GetThriftProtocolType(returnType)); } // coerce the type if possible TypeCoercion coercion = null; if (_coercions.TryGetValue(rawType, out coercion)) { return(coercion.ThriftType.ProtocolType); } if (IsNullableEnum(rawType)) { return(ThriftProtocolType.Enum); } return(ThriftProtocolType.Unknown); }