Пример #1
0
        public static ThriftType Enum(ThriftEnumMetadata enumMetadata, bool isNullable = false)
        {
            Guard.ArgumentNotNull(enumMetadata, nameof(enumMetadata));
            var tt = new ThriftType(enumMetadata);

            return(isNullable ? tt.CoerceTo(typeof(Nullable <>).MakeGenericType(enumMetadata.EnumType)) : tt);
        }
Пример #2
0
        public static ThriftType Dictionary(ThriftType keyType, ThriftType valueType)
        {
            Guard.ArgumentNotNull(keyType, nameof(keyType));
            Guard.ArgumentNotNull(valueType, nameof(valueType));

            return(Dictionary(new DefaultThriftTypeReference(keyType), new DefaultThriftTypeReference(valueType)));
        }
Пример #3
0
        private ThriftType BuildThriftType(Type csharpType)
        {
            ThriftType thriftType = _typeCache.GetOrAdd(csharpType, t => BuildThriftTypeInternal(csharpType));

            if (_stack.Value.Count == 0)
            {
                /*
                 * The stack represents the processing of nested types, so when the stack is empty
                 * at this point, we've just finished processing and caching the originally requested
                 * type. There may be some unresolved type references we should revisit now.
                 */
                var unresolvedCSharpTypes = _deferredTypesWorkList.Value;
                do
                {
                    if (unresolvedCSharpTypes.Count == 0)
                    {
                        break;
                    }
                    Type unresolvedType = unresolvedCSharpTypes.Pop();
                    if (!_typeCache.ContainsKey(unresolvedType))
                    {
                        _typeCache.GetOrAdd(unresolvedType, t => BuildThriftTypeInternal(unresolvedType));
                    }
                } while (true);
            }
            return(thriftType);
        }
Пример #4
0
        public ThriftType GetThriftTypeFromCache(Type csharpType)
        {
            ThriftType tt = null;

            _typeCache.TryGetValue(csharpType, out tt);
            return(tt);
        }
Пример #5
0
        public TypeCoercion(ThriftType thriftType)
        {
            Guard.ArgumentNotNull(thriftType, nameof(thriftType));
            var typeInfo = thriftType.CSharpType.GetTypeInfo();

            if (!typeInfo.IsGenericType || !typeInfo.GetGenericTypeDefinition().Equals(typeof(Nullable <>)))
            {
                throw new ArgumentException($"only nullable type can be used by {nameof(TypeCoercion)}, actual thrift type is: {thriftType.CSharpType.FullName}");
            }
            _underlyingType = Nullable.GetUnderlyingType(thriftType.CSharpType);

            this.ThriftType = thriftType;

            var p          = Expression.Parameter(thriftType.CSharpType);
            var methodName = nameof(Nullable <int> .GetValueOrDefault);
            var m          = thriftType.CSharpType.GetMethod(methodName, new Type[0]);
            var call       = Expression.Call(p, m);

            this.ToThrift = Expression.Lambda(call, p).Compile();

            var p1     = Expression.Parameter(_underlyingType, "v");
            var ctor   = typeInfo.GetConstructor(new Type[] { _underlyingType });
            var newExp = Expression.New(ctor, p1);

            this.FromThrift = Expression.Lambda(newExp, p1).Compile();
        }
Пример #6
0
        /// <summary>
        /// Gets the ThriftType for the specified Java type.  The native Thrift type for the Java type will
        /// be inferred from the Java type, and if necessary type coercions will be applied.
        /// </summary>
        /// <param name="csharpType"></param>
        /// <returns>the ThriftType for the specified csharp type; never null</returns>
        public ThriftType GetThriftType(Type csharpType)
        {
            ThriftType thriftType = GetThriftTypeFromCache(csharpType);

            if (thriftType == null)
            {
                thriftType = BuildThriftType(csharpType);
            }
            return(thriftType);
        }
Пример #7
0
        public ThriftType Get()
        {
            ThriftType resolvedType = catalog.GetThriftTypeFromCache(this.CSharpType);

            if (resolvedType == null)
            {
                throw new NotSupportedException(
                          $"Attempted to resolve a recursive reference to type '{this.CSharpType.FullName}' before the referenced type was cached (most likely a recursive type support bug)");
            }
            return(resolvedType);
        }
Пример #8
0
        private ThriftType(ThriftType underlyingType, Type nullableType)
        {
            this.CSharpType    = nullableType;
            this.UncoercedType = underlyingType;

            this.ProtocolType  = underlyingType.ProtocolType;
            keyTypeReference   = null;
            valueTypeReference = null;
            structMetadata     = null;
            enumMetadata       = underlyingType.enumMetadata;
        }
Пример #9
0
        private IThriftTypeReference GetThriftTypeReference(Type csharpType, Recursiveness recursiveness)
        {
            ThriftType thriftType = GetThriftTypeFromCache(csharpType);

            if (thriftType == null)
            {
                if (recursiveness == Recursiveness.Forced ||
                    (recursiveness == Recursiveness.Allowed && _stack.Value.Contains(csharpType)))
                {
                    // recursion: return an unresolved ThriftTypeReference
                    _deferredTypesWorkList.Value.Push(csharpType);
                    return(new RecursiveThriftTypeReference(this, csharpType));
                }
                else
                {
                    thriftType = _typeCache.GetOrAdd(csharpType, t => BuildThriftType(t));
                }
            }
            return(new DefaultThriftTypeReference(thriftType));
        }
Пример #10
0
        public override bool Equals(object o)
        {
            if (this != null && o != null && Object.ReferenceEquals(this, o))
            {
                return(true);
            }
            if (o == null || !this.GetType().Equals(o.GetType()))
            {
                return(false);
            }

            ThriftType that = (ThriftType)o;

            if (this.CSharpType != null ? !this.CSharpType.Equals(that.CSharpType) : that.CSharpType != null)
            {
                return(false);
            }
            if (!this.ProtocolType.Equals(that.ProtocolType))
            {
                return(false);
            }

            return(true);
        }
Пример #11
0
 public DefaultThriftTypeReference(ThriftType thriftType)
 {
     this.thriftType = thriftType;
 }
Пример #12
0
        public static ThriftType Array(ThriftType valueType)
        {
            Guard.ArgumentNotNull(valueType, nameof(valueType));

            return(Array(new DefaultThriftTypeReference(valueType)));
        }
Пример #13
0
 public void AddThriftType(ThriftType thriftType)
 {
     _manualTypes.AddOrUpdate(thriftType.CSharpType, thriftType, (ket, old) => thriftType);
 }
Пример #14
0
        // 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}");
        }