public XdrPropertySerializationDescriptor(PropertyInfo prop)
        {
            Property      = prop;
            PrimitiveType = prop.PropertyType;
            if (prop.GetMethod == null)
            {
                throw new InvalidOperationException($"Property {FullPropertyName} does not have getter and cannot be serialized.");
            }
            if (prop.SetMethod == null)
            {
                throw new InvalidOperationException($"Property {FullPropertyName} does not have setter and cannot be serialized.");
            }
            if (PrimitiveType == typeof(object))
            {
                throw new InvalidOperationException($"Generalized object serialization not supported. Check {FullPropertyName}.");
            }

            //determine optional property
            IsOptional = prop.GetCustomAttribute <XdrFieldAttribute>().Optional;

            //if this is a primitive type, we are done
            if (PrimitiveValueTypes.Contains(PrimitiveType))
            {
                return;
            }

            //check if it's a serializable contract by itself
            if (IsXdrContractType(PrimitiveType))
            {
                GenericArgument = PrimitiveType;
                PrimitiveType   = typeof(object);
                return;
            }

            //handle enums
            if (PrimitiveType.IsEnum)
            {
                //verify enum underlying type
                EnsureValidEnumType(PrimitiveType);
                //and treat it as int32
                PrimitiveType = typeof(int);
                return;
            }

            //handle nullable types
            if (PrimitiveType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                var valueType = PrimitiveType.GetGenericArguments().SingleOrDefault();
                if (IsPrimitiveValueType(valueType))
                {
                    IsOptional    = true;
                    IsNullable    = true;
                    PrimitiveType = valueType;
                    return;
                }
            }

            //handle lists serialization
            if (PrimitiveType.GetGenericTypeDefinition() == typeof(List <>))
            {
                var listGenericType = PrimitiveType.GetGenericArguments().SingleOrDefault();
                if (IsXdrContractType(listGenericType) || IsPrimitiveValueType(listGenericType))
                {
                    PrimitiveType   = typeof(List <>);
                    GenericArgument = listGenericType;
                    return;
                }
            }

            //no suitable primitive serializer found
            throw new InvalidOperationException($"{PrimitiveType.FullName} XDR serialization is not supported. Check {FullPropertyName}.");
        }