diff --git a/Refit/Attributes.cs b/Refit/Attributes.cs index 1d8539afb..79dc18d76 100644 --- a/Refit/Attributes.cs +++ b/Refit/Attributes.cs @@ -70,7 +70,7 @@ public override HttpMethod Method { } public enum BodySerializationMethod { - Json, UrlEncoded + Json, UrlEncoded, Custom } [AttributeUsage(AttributeTargets.Parameter)] diff --git a/Refit/RefitSettings.cs b/Refit/RefitSettings.cs index 370ee1716..4327b3f42 100644 --- a/Refit/RefitSettings.cs +++ b/Refit/RefitSettings.cs @@ -1,4 +1,8 @@ -using System.Reflection; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; namespace Refit { @@ -7,9 +11,12 @@ public class RefitSettings public RefitSettings() { UrlParameterFormatter = new DefaultUrlParameterFormatter(); + CustomSerializers = new Dictionary(); } public IUrlParameterFormatter UrlParameterFormatter { get; set; } + + public Dictionary CustomSerializers { get; private set; } } public interface IUrlParameterFormatter @@ -24,4 +31,10 @@ public virtual string Format(object parameterValue, ParameterInfo parameterInfo) return parameterValue != null ? parameterValue.ToString() : null; } } + + public interface ITypeSerializer + { + HttpContent SerializeAsHttpContent(object value); + Task DeserializeFromHttpContent(HttpContent content); + } } \ No newline at end of file diff --git a/Refit/RequestBuilderImplementation.cs b/Refit/RequestBuilderImplementation.cs index 5129c574e..16d386def 100644 --- a/Refit/RequestBuilderImplementation.cs +++ b/Refit/RequestBuilderImplementation.cs @@ -92,6 +92,10 @@ public Func BuildRequestFactoryForMethod(string me ret.Content = new StringContent(stringParam); } else { switch (restMethod.BodyParameterInfo.Item1) { + case BodySerializationMethod.Custom: + var param = paramList[i]; + ret.Content = settings.CustomSerializers[param.GetType()].SerializeAsHttpContent(param); + break; case BodySerializationMethod.UrlEncoded: ret.Content = new FormUrlEncodedContent(new FormValueDictionary(paramList[i])); break; @@ -230,6 +234,11 @@ Func> buildCancellableTaskFuncF throw await ApiException.Create(resp); } + ITypeSerializer customSerializer; + if (settings.CustomSerializers.TryGetValue(restMethod.SerializedReturnType, out customSerializer)) { + return (T)await customSerializer.DeserializeFromHttpContent(resp.Content); + } + var ms = new MemoryStream(); var fromStream = await resp.Content.ReadAsStreamAsync(); await fromStream.CopyToAsync(ms, 4096, ct); @@ -317,6 +326,7 @@ public class RestMethodInfo public Dictionary ParameterInfoMap { get; set; } public Type ReturnType { get; set; } public Type SerializedReturnType { get; set; } + public RefitSettings RefitSettings { get; set; } // Placeholder until #80 is merged. How lazy am I! static readonly Regex parameterRegex = new Regex(@"{(.*?)}"); @@ -413,8 +423,12 @@ string getUrlNameForParameter(ParameterInfo paramInfo) Tuple findBodyParameter(List parameterList) { var bodyParams = parameterList - .Select(x => new { Parameter = x, BodyAttribute = x.GetCustomAttributes(true).OfType().FirstOrDefault() }) - .Where(x => x.BodyAttribute != null) + .Select(x => new { + Parameter = x, + BodyAttribute = x.GetCustomAttributes(true).OfType().FirstOrDefault(), + HasCustomSerializer = RefitSettings.CustomSerializers.ContainsKey(x.ParameterType) + }) + .Where(x => x.BodyAttribute != null || x.HasCustomSerializer) .ToList(); if (bodyParams.Count > 1) { @@ -426,7 +440,10 @@ Tuple findBodyParameter(List parame } var ret = bodyParams[0]; - return Tuple.Create(ret.BodyAttribute.SerializationMethod, parameterList.IndexOf(ret.Parameter)); + var serializationMethod = ret.HasCustomSerializer + ? BodySerializationMethod.Custom + : ret.BodyAttribute.SerializationMethod; + return Tuple.Create(serializationMethod, parameterList.IndexOf(ret.Parameter)); } Dictionary parseHeaders(MethodInfo methodInfo)