Last active
October 24, 2023 15:31
-
-
Save bennor/c73870e810f8245b2b1d to your computer and use it in GitHub Desktop.
A polyfill for Refit 2.0+ in scripting environments (e.g. LINQPad). Warning: This won't work on all platforms Refit 2.0+ supports (e.g. iOS, maybe WinRT?).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Net.Http; | |
using Castle.DynamicProxy; // From Castle.Core | |
using Refit; | |
public class ProxyRestService | |
{ | |
static readonly ProxyGenerator Generator = new ProxyGenerator(); | |
public static T For<T>(HttpClient client) | |
where T : class | |
{ | |
if(!typeof(T).IsInterface) { | |
throw new InvalidOperationException("T must be an interface."); | |
} | |
var interceptor = new RestMethodInterceptor<T>(client); | |
return Generator.CreateInterfaceProxyWithoutTarget<T>(interceptor); | |
} | |
public static T For<T>(string hostUrl) | |
where T : class | |
{ | |
var client = new HttpClient() { BaseAddress = new Uri(hostUrl) }; | |
return For<T>(client); | |
} | |
class RestMethodInterceptor<T> : IInterceptor | |
{ | |
static readonly Dictionary<string, Func<HttpClient, object[], object>> methodImpls | |
= RequestBuilder.ForType<T>().InterfaceHttpMethods | |
.ToDictionary(k => k, v => RequestBuilder.ForType<T>().BuildRestResultFuncForMethod(v)); | |
readonly HttpClient client; | |
public RestMethodInterceptor(HttpClient client) | |
{ | |
this.client = client; | |
} | |
public void Intercept(IInvocation invocation) | |
{ | |
if (!methodImpls.ContainsKey(invocation.Method.Name)) { | |
throw new NotImplementedException(); | |
} | |
invocation.ReturnValue = methodImpls[invocation.Method.Name](client, invocation.Arguments); | |
} | |
} | |
} |
Thanks for this gist. I use LinqPad all the time and have been wanting to play around with Refit. I was thinking about making a Nuget package out of this gist for folks with LinqPad Developer or Premium. Are you okay with this?
@jrotello that would be very handy, did you end up doing this?
@bennor Do you have a more current version of this gist for Refit 4.X?
@jrotello Did you make a NuGet package?
I get the error below on InterfaceHttpMethods here and I can't figure it out:
static readonly Dictionary<string, Func<HttpClient, object[], object>> methodImpls
= RequestBuilder.ForType<T>().InterfaceHttpMethods
.ToDictionary(k => k, v => RequestBuilder.ForType<T>().BuildRestResultFuncForMethod(v));
CS1061 'IRequestBuilder' does not contain a definition for 'InterfaceHttpMethods' and no extension method 'InterfaceHttpMethods' accepting a first argument of type 'IRequestBuilder' could be found (press F4 to add a using directive or assembly reference)
@jrotello 100% okay with it (only just saw your comment). But as has been mentioned -- the above code isn't compatible with Refit 4+.
just use the following to create the dictionary:
static readonly Dictionary<string, Func<HttpClient, object[], object>> methodImpls
= typeof(T).GetMethods().Select(m => m.Name)
.ToDictionary(k => k, v => RequestBuilder.ForType<T>().BuildRestResultFuncForMethod(v));
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This class is a shim for Refit 2.0+ to fix the fact that the new
InterfaceStubGenerator
approach isn't compatible with all environments/NuGet consumers (e.g. LINQPad, Paket, etc).Just drop this class in your project, reference
Castle.Core
and callProxyRestService.For<ISomeApi>(...)
instead ofRestService.For<ISomeApi>()
.