Skip to content

Instantly share code, notes, and snippets.

@bennor
Last active October 24, 2023 15:31
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bennor/c73870e810f8245b2b1d to your computer and use it in GitHub Desktop.
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?).
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);
}
}
}
@andylech
Copy link

andylech commented Mar 5, 2018

@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)

@bennor
Copy link
Author

bennor commented Jul 5, 2018

@jrotello 100% okay with it (only just saw your comment). But as has been mentioned -- the above code isn't compatible with Refit 4+.

@gsoulavy
Copy link

gsoulavy commented Nov 14, 2019

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