Refit: Allow: Aggregated interfaces

Created on 24 Aug 2015  路  6Comments  路  Source: reactiveui/refit

Currently, if an API interface A(HasRefitHttpMethodAttribute) is an aggregation of other interfaces(HasRefitHttpMethodAttribute) then the generated stub for A doesn麓t implement the aggregated interfaces;

using Refit
...
interface InterfaceA : InterfaceB
{
    [Get("/ping")]
    Task Ping(); 
}

interface InterfaceB
{
    [Get("/ping")]
    Task Pong(); 
}

The generated stub look like this, and doesn麓t obviously compile

using Refit
...
class AutoGeneratedA : InterfaceA
{
    ...
    public Task Ping() { ... }
}

class AutoGeneratedB : InterfaceB
{
    ...
    public Task Pong() { ... }
}

This should/could have been the following

using Refit
...
class AutoGeneratedA  : AutoGeneratedB, InterfaceA
{
    ...
    public Task Ping() { ... }
}

class AutoGeneratedB : InterfaceB
{
    ...
    public Task Pong() { ... }
}

I麓m trying to seggregate the interface to better know what client a particular ViewModel(of my MVVM) uses or is supposed to use, i use a IoC container to inject specific implementations.

The registration uses reflection:

using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
using Refit;

namespace Service.Clients
{
    using Core.Common;
    using IoC;

    public class RestServicesWrapper
    {
        static RestServicesWrapper()
        {
            RestServiceType = typeof(RestService);

            var parameterTypes = new Type[] { typeof(HttpClient) };
            RestServiceFactory = RestServiceType.GetRuntimeMethod("For", parameterTypes);
            WebApiClientsAssembly = typeof(RestServicesWrapper).GetTypeInfo().Assembly; ;
        }

        private static MethodInfo RestServiceFactory { get; set; }
        private static Type RestServiceType { get; set; }
        private static Assembly WebApiClientsAssembly { get; set; }

        public static object For(Type serviceContractType, HttpClient httpClient)
        {
            return RestServiceFactory
                .MakeGenericMethod(serviceContractType)
                .Invoke(RestServiceType, new object[] { httpClient });
        }

        public static void RegisterServices()
        {
            var httpClient = new HttpClient();

            var services =
                from service in WebApiClientsAssembly.ExportedTypes
                let type = service.GetTypeInfo()
                where type.GetCustomAttributes<WebApiContractAttribute>().Any() // A custom marker attribute
                select service;

            var container = Container.Default;

            foreach (var service in services)
                container.Register(service, () => For(service, httpClient));
        }
    }
}
outdated

Most helpful comment

Yes, I was thinking about this. I'll try to see if I could do a PR for this, maybe @paulcbetts hasn't much time at the moment. :)

All 6 comments

Hi any word on this. at least a "NO WAY"(with why) would be apreciated! @paulcbetts :)
Just for the love your "reactive endeavours"

For me it is an important missing feature too!

Your suggestion could not be used because multiple classes inheritance isn't supported by C#.

Imagine you have :

interface A : B, C
{
    [Get("/ping")]
    Task Ping(); 
}

interface B
{
    [Get("/pong")]
    Task Pong(); 
}

interface C
{
    [Get("/pang")]
    Task Pang(); 
}

Then, this is not valid :

using Refit
...
class A : AutoGeneratedB, AutoGeneratedC, A // <- Not valid !
{
    ...
    public Task Ping() { ... }
}

class AutoGeneratedB : B
{
    ...
    public Task Pong() { ... }
}

class AutoGeneratedC : C
{
    ...
    public Task Pang() { ... }
}

But you could do that at generation, all methods from inherited interfaces could be reflected and regenerated each time by all registered child interfaces.

but this is valid

using Refit
...
class A : AutoGeneratedB, A
{
    ...
    public Task Ping() { ... }
}

class AutoGeneratedB : AutoGeneratedC, B
{
    ...
    public Task Pong() { ... }
}

class AutoGeneratedC : C
{
    ...
    public Task Pang() { ... }
}

//And so is this

using Refit
...
class AutoGeneratedABC : A, B, C
{
    ...
    Task A.Ping() { ... }
    ...
    Task B.Pong() { ... }
    ...
    Task C.Pang() { ... }
}

Yes, I was thinking about this. I'll try to see if I could do a PR for this, maybe @paulcbetts hasn't much time at the moment. :)

Any progress here? This feature would be really a great enhancement. Imagine the possibilities!

This too was just done in #633 - so this can be closed as well 馃槉

Was this page helpful?
0 / 5 - 0 ratings