Skip to content

Refit 2.0.0

Compare
Choose a tag to compare
@anaisbetts anaisbetts released this 13 Oct 00:40
· 1664 commits to main since this release

What's New

Support for Xamarin.iOS (#38)

Refit 2.0 uses a completely different system to generate the backing classes for your interfaces. In Refit 1.0, these classes would be generated at runtime using Castle.Core, which worked on most platforms, but fails on any Ahead-of-Time compiled platform, such as Xamarin.iOS.

Refit 2.0 instead generates classes at compile-time, by analyzing your app's source files with Roslyn, and generates a new RefitStubs.cs file that will be compiled along with your class. As well as enabling Xamarin.iOS support, this class is easily subclassed and extended via partial classes, so customizing individual method behavior is now much easier

Observables in Refit are now Cold (#56, thanks to @Balauru for some of the work)

Observables in Refit 1.x are backed by AsyncSubject, meaning that they replay a single result to subscribers, even after the network request ends. In Refit 2.0, Observables now do no work until Subscribed to, and each Subscription will generate a new network request, in line with Retrofit. Observables in Refit 2.0 now also will cancel network operations if the Subscription is disposed, allowing you to efficiently cancel requests if they are no longer needed.

Before:

var observable = someRestService.ReturnsAnObservable();
var result1 = await observable;
var result2 = await observable;

// result2 is just a replayed result1, the network request was made when
// we called ReturnsAnObservable regardless if anyone cared.
result1 == result2;
>>> true

After:

// Does nothing
var observable = someRestService.ReturnsAnObservable();

// Makes a web request
var result1 = await observable;

// Makes a *different* web request
var result2 = await observable;

result1 == result2;
>>> maybe?

Form Property Aliasing (#55, thanks @bennor)

When POSTing bodies serialized via BodySerializationMethod.UrlEncoded, the AliasAs tag now also works on properties in the model class:

Before:

public interface IMeasurementProtocolApi
{
    [Post("/collect")]
    Task Collect([Body(BodySerializationMethod.UrlEncoded)] Measurement measurement);
}

public class Measurement
{
    public string t { get; set; } // This isn't even the worst of them
}

await api.Collect(new Measurement { t = "what even is t?" });

After:

// This part doesn't change
public interface IMeasurementProtocolApi
{
    [Post("/collect")]
    Task Collect([Body(BodySerializationMethod.UrlEncoded)] Measurement measurement);
}

// This stuff does
public Measurement
{
    [AliasAs("t")] 
    public string Type { get; set; }
}

await api.Collect(new Measurement { Type = "event" });