Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions InterfaceStubGenerator.Core/InterfaceStubGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ public class ClassTemplateInfo
public string TypeParameters => TypeParametersInfo != null ? string.Join(", ", TypeParametersInfo) : null;
}

public class TypeInfo : ICloneable
public class TypeInfo
{
public string Name { get; set; }
public List<TypeInfo> Children { get; set; }
Expand All @@ -388,11 +388,6 @@ public TypeInfo Clone()
return CloneImpl() as TypeInfo;
}

object ICloneable.Clone()
{
throw new NotImplementedException();
}

protected virtual object CloneImpl()
{
return new TypeInfo
Expand Down
16 changes: 15 additions & 1 deletion Refit.HttpClientFactory/HttpClientFactoryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.DependencyInjection;

namespace Refit
{
Expand All @@ -18,5 +19,18 @@ public static IHttpClientBuilder AddRefitClient<T>(this IServiceCollection servi
return services.AddHttpClient(UniqueName.ForType<T>())
.AddTypedClient((client, serviceProvider) => RestService.For<T>(client, serviceProvider.GetService<IRequestBuilder<T>>()));
}

/// <summary>
/// Adds a Refit client to the DI container
/// </summary>
/// <param name="services">container</param>
/// <param name="refitInterfaceType">Type of the Refit interface</typeparam>
/// <param name="settings">Optional. Settings to configure the instance with</param>
/// <returns></returns>
public static IHttpClientBuilder AddRefitClient(this IServiceCollection services, Type refitInterfaceType, RefitSettings settings = null)
{
return services.AddHttpClient(UniqueName.ForType(refitInterfaceType))
.AddTypedClient((client, serviceProvider) => RestService.For(refitInterfaceType, client, settings));
}
}
}
11 changes: 11 additions & 0 deletions Refit.Tests/RestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1290,5 +1290,16 @@ public void ShouldThrowArgumentExceptionIfHostUrlIsWhitespace()

Assert.False(true, "Exception not thrown.");
}

[Fact]
public void NonGenericCreate()
{
var expectedBaseAddress = "http://example.com/api";
var inputBaseAddress = "http://example.com/api/";

var fixture = RestService.For(typeof(ITrimTrailingForwardSlashApi), inputBaseAddress) as ITrimTrailingForwardSlashApi;

Assert.Equal(fixture.Client.BaseAddress.AbsoluteUri, expectedBaseAddress);
}
}
}
13 changes: 10 additions & 3 deletions Refit/CachedRequestBuilderImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@

namespace Refit
{
class CachedRequestBuilderImplementation<T> : IRequestBuilder<T>
class CachedRequestBuilderImplementation<T> : CachedRequestBuilderImplementation, IRequestBuilder<T>
{
public CachedRequestBuilderImplementation(IRequestBuilder<T> innerBuilder)
public CachedRequestBuilderImplementation(IRequestBuilder<T> innerBuilder) : base(innerBuilder)
{
}
}

class CachedRequestBuilderImplementation : IRequestBuilder
{
public CachedRequestBuilderImplementation(IRequestBuilder innerBuilder)
{
this.innerBuilder = innerBuilder;
}

readonly IRequestBuilder<T> innerBuilder;
readonly IRequestBuilder innerBuilder;
readonly ConcurrentDictionary<string, Func<HttpClient, object[], object>> methodDictionary = new ConcurrentDictionary<string, Func<HttpClient, object[], object>>();

public Func<HttpClient, object[], object> BuildRestResultFuncForMethod(string methodName, Type[] parameterTypes = null, Type[] genericArgumentTypes = null)
Expand Down
10 changes: 10 additions & 0 deletions Refit/RequestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,15 @@ public static IRequestBuilder<T> ForType<T>()
{
return PlatformRequestBuilderFactory.Create<T>(null);
}

public static IRequestBuilder ForType(Type refitInterfaceType, RefitSettings settings)
{
return PlatformRequestBuilderFactory.Create(refitInterfaceType, settings);
}

public static IRequestBuilder ForType(Type refitInterfaceType)
{
return PlatformRequestBuilderFactory.Create(refitInterfaceType, null);
}
}
}
6 changes: 6 additions & 0 deletions Refit/RequestBuilderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace Refit
interface IRequestBuilderFactory
{
IRequestBuilder<T> Create<T>(RefitSettings settings);
IRequestBuilder Create(Type refitInterfaceType, RefitSettings settings);
}

class RequestBuilderFactory : IRequestBuilderFactory
Expand All @@ -16,5 +17,10 @@ public IRequestBuilder<T> Create<T>(RefitSettings settings = null)
{
return new CachedRequestBuilderImplementation<T>(new RequestBuilderImplementation<T>(settings));
}

public IRequestBuilder Create(Type refitInterfaceType, RefitSettings settings = null)
{
return new CachedRequestBuilderImplementation(new RequestBuilderImplementation(refitInterfaceType, settings));
}
}
}
2 changes: 1 addition & 1 deletion Refit/RequestBuilderImplementation.TaskToObservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Refit
{
partial class RequestBuilderImplementation<TApi>
partial class RequestBuilderImplementation
{
sealed class TaskToObservable<T> : IObservable<T>
{
Expand Down
24 changes: 15 additions & 9 deletions Refit/RequestBuilderImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@

namespace Refit
{
partial class RequestBuilderImplementation<TApi> : IRequestBuilder<TApi>
class RequestBuilderImplementation<TApi> : RequestBuilderImplementation, IRequestBuilder<TApi>
{
public RequestBuilderImplementation(RefitSettings refitSettings = null) : base(typeof(TApi), refitSettings)
{
}
}

partial class RequestBuilderImplementation : IRequestBuilder
{
static readonly ISet<HttpMethod> BodylessMethods = new HashSet<HttpMethod>
{
Expand All @@ -28,25 +35,24 @@ partial class RequestBuilderImplementation<TApi> : IRequestBuilder<TApi>
readonly RefitSettings settings;
public Type TargetType { get; }

public RequestBuilderImplementation(RefitSettings refitSettings = null)
public RequestBuilderImplementation(Type refitInterfaceType, RefitSettings refitSettings = null)
{
Type targetInterface = typeof(TApi);
Type[] targetInterfaceInheritedInterfaces = targetInterface.GetInterfaces();
Type[] targetInterfaceInheritedInterfaces = refitInterfaceType.GetInterfaces();

settings = refitSettings ?? new RefitSettings();
serializer = settings.ContentSerializer;
interfaceGenericHttpMethods = new ConcurrentDictionary<CloseGenericMethodKey, RestMethodInfo>();

if (targetInterface == null || !targetInterface.GetTypeInfo().IsInterface)
if (refitInterfaceType == null || !refitInterfaceType.GetTypeInfo().IsInterface)
{
throw new ArgumentException("targetInterface must be an Interface");
}

TargetType = targetInterface;
TargetType = refitInterfaceType;

var dict = new Dictionary<string, List<RestMethodInfo>>();

AddInterfaceHttpMethods(targetInterface, dict);
AddInterfaceHttpMethods(refitInterfaceType, dict);
foreach (var inheritedInterface in targetInterfaceInheritedInterfaces)
{
AddInterfaceHttpMethods(inheritedInterface, dict);
Expand Down Expand Up @@ -152,7 +158,7 @@ public Func<HttpClient, object[], object> BuildRestResultFuncForMethod(string me
// difficult to upcast Task<object> to an arbitrary T, especially
// if you need to AOT everything, so we need to reflectively
// invoke buildTaskFuncForMethod.
var taskFuncMi = GetType().GetMethod(nameof(BuildTaskFuncForMethod), BindingFlags.NonPublic | BindingFlags.Instance);
var taskFuncMi = typeof(RequestBuilderImplementation).GetMethod(nameof(BuildTaskFuncForMethod), BindingFlags.NonPublic | BindingFlags.Instance);
var taskFunc = (MulticastDelegate)(restMethod.IsApiResponse ?
taskFuncMi.MakeGenericMethod(restMethod.SerializedReturnType, restMethod.SerializedGenericArgument) :
taskFuncMi.MakeGenericMethod(restMethod.SerializedReturnType, restMethod.SerializedReturnType)).Invoke(this, new[] { restMethod });
Expand All @@ -161,7 +167,7 @@ public Func<HttpClient, object[], object> BuildRestResultFuncForMethod(string me
}

// Same deal
var rxFuncMi = GetType().GetMethod(nameof(BuildRxFuncForMethod), BindingFlags.NonPublic | BindingFlags.Instance);
var rxFuncMi = typeof(RequestBuilderImplementation).GetMethod(nameof(BuildRxFuncForMethod), BindingFlags.NonPublic | BindingFlags.Instance);
var rxFunc = (MulticastDelegate)(restMethod.IsApiResponse ?
rxFuncMi.MakeGenericMethod(restMethod.SerializedReturnType, restMethod.SerializedGenericArgument) :
rxFuncMi.MakeGenericMethod(restMethod.SerializedReturnType, restMethod.SerializedReturnType)).Invoke(this, new[] { restMethod });
Expand Down
53 changes: 45 additions & 8 deletions Refit/RestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,49 @@ public static T For<T>(HttpClient client, IRequestBuilder<T> builder)

public static T For<T>(HttpClient client, RefitSettings settings)
{
IRequestBuilder<T> requestBuilder = RequestBuilder.ForType<T>(settings);
var requestBuilder = RequestBuilder.ForType<T>(settings);

return For<T>(client, requestBuilder);
return For(client, requestBuilder);
}

public static T For<T>(HttpClient client) => For<T>(client, (RefitSettings)null);

public static T For<T>(string hostUrl, RefitSettings settings)
{
var client = CreateHttpClient(hostUrl, settings);

return For<T>(client, settings);
}

public static T For<T>(string hostUrl) => For<T>(hostUrl, null);

public static object For(Type refitInterfaceType, HttpClient client, IRequestBuilder builder)
{
var generatedType = TypeMapping.GetOrAdd(refitInterfaceType, GetGeneratedType(refitInterfaceType));

return Activator.CreateInstance(generatedType, client, builder);
}

public static object For(Type refitInterfaceType, HttpClient client, RefitSettings settings)
{
var requestBuilder = RequestBuilder.ForType(refitInterfaceType, settings);

return For(refitInterfaceType, client, requestBuilder);
}

public static object For(Type refitInterfaceType, HttpClient client) => For(refitInterfaceType, client, (RefitSettings)null);

public static object For(Type refitInterfaceType, string hostUrl, RefitSettings settings)
{
var client = CreateHttpClient(hostUrl, settings);

return For(refitInterfaceType, client, settings);
}

public static object For(Type refitInterfaceType, string hostUrl) => For(refitInterfaceType, hostUrl, null);


public static HttpClient CreateHttpClient(string hostUrl, RefitSettings settings)
{
if (string.IsNullOrWhiteSpace(hostUrl))
{
Expand All @@ -56,21 +91,23 @@ public static T For<T>(string hostUrl, RefitSettings settings)
}
}

var client = new HttpClient(innerHandler ?? new HttpClientHandler()) { BaseAddress = new Uri(hostUrl.TrimEnd('/')) };
return For<T>(client, settings);
return new HttpClient(innerHandler ?? new HttpClientHandler()) { BaseAddress = new Uri(hostUrl.TrimEnd('/')) };
}

public static T For<T>(string hostUrl) => For<T>(hostUrl, null);

static Type GetGeneratedType<T>()
{
string typeName = UniqueName.ForType<T>();
return GetGeneratedType(typeof(T));
}

static Type GetGeneratedType(Type refitInterfaceType)
{
string typeName = UniqueName.ForType(refitInterfaceType);

var generatedType = Type.GetType(typeName);

if (generatedType == null)
{
var message = typeof(T).Name + " doesn't look like a Refit interface. Make sure it has at least one " + "method with a Refit HTTP method attribute and Refit is installed in the project.";
var message = refitInterfaceType.Name + " doesn't look like a Refit interface. Make sure it has at least one " + "method with a Refit HTTP method attribute and Refit is installed in the project.";

throw new InvalidOperationException(message);
}
Expand Down
21 changes: 14 additions & 7 deletions Refit/UniqueName.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
namespace Refit
using System;

namespace Refit
{
internal class UniqueName
{
public static string ForType<T>()
{
return ForType(typeof(T));
}

public static string ForType(Type refitInterfaceType)
{
string typeName;

if (typeof(T).IsNested)
if (refitInterfaceType.IsNested)
{
var className = "AutoGenerated" + typeof(T).DeclaringType.Name + typeof(T).Name;
typeName = typeof(T).AssemblyQualifiedName.Replace(typeof(T).DeclaringType.FullName + "+" + typeof(T).Name, typeof(T).Namespace + "." + className);
var className = "AutoGenerated" + refitInterfaceType.DeclaringType.Name + refitInterfaceType.Name;
typeName = refitInterfaceType.AssemblyQualifiedName.Replace(refitInterfaceType.DeclaringType.FullName + "+" + refitInterfaceType.Name, refitInterfaceType.Namespace + "." + className);
}
else
{
var className = "AutoGenerated" + typeof(T).Name;
var className = "AutoGenerated" + refitInterfaceType.Name;

if (typeof(T).Namespace == null)
if (refitInterfaceType.Namespace == null)
{
className = $"{className}.{className}";
}

typeName = typeof(T).AssemblyQualifiedName.Replace(typeof(T).Name, className);
typeName = refitInterfaceType.AssemblyQualifiedName.Replace(refitInterfaceType.Name, className);
}

return typeName;
Expand Down