You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Blazor Web App中结合具体实现与Refit复用同一服务?

解决方案

你可以通过两种简洁的方式实现共用IHelloWorld接口的需求,无需大量重复代码:

方案一:继承接口+DI映射

  1. 调整Refit客户端接口,让它直接继承IHelloWorld,并在方法上添加Refit特性(用new关键字明确隐藏基类方法,避免编译器警告):
// 共用接口
public interface IHelloWorld
{
    Task<string> GetGreetingAsync();
}

// Refit客户端接口
public interface IHelloWorldClient : IHelloWorld
{
    [Get("/api/helloworld/greeting")]
    new Task<string> GetGreetingAsync();
}
  1. 分别配置两端的DI:
  • 服务器端:直接注册IHelloWorld到具体实现:
builder.Services.AddScoped<IHelloWorld, HelloWorld>();
  • 客户端(WASM):先注册Refit客户端,再将IHelloWorld映射到IHelloWorldClient的实例:
// 注册Refit客户端
builder.Services.AddRefitClient<IHelloWorldClient>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

// 将IHelloWorld关联到Refit代理
builder.Services.AddScoped<IHelloWorld>(sp => sp.GetRequiredService<IHelloWorldClient>());

这种方式让两端注入IHelloWorld时,自动获取对应环境的实现:服务器端用本地逻辑,客户端用Refit生成的API代理。

方案二:轻量适配类(推荐)

如果不想用继承带来的方法隐藏逻辑,可以写一个极简的适配类,将IHelloWorldClient包装成IHelloWorld实现:

public class HelloWorldClientAdapter : IHelloWorld
{
    private readonly IHelloWorldClient _client;

    public HelloWorldClientAdapter(IHelloWorldClient client)
    {
        _client = client;
    }

    public Task<string> GetGreetingAsync()
    {
        return _client.GetGreetingAsync();
    }
}

然后客户端DI注册:

builder.Services.AddRefitClient<IHelloWorldClient>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

// 注册适配类作为IHelloWorld的实现
builder.Services.AddScoped<IHelloWorld, HelloWorldClientAdapter>();

适配类代码量极少,逻辑清晰,避免了继承的潜在问题,也不算“重复代码”——它只是做了一层简单的接口转换。

关键注意事项

  • 确保IHelloWorld和IHelloWorldClient的方法签名完全一致(返回类型、参数、异步标识都要匹配),否则Refit生成代理或DI映射会失败。
  • 客户端的BaseAddress要正确指向服务器API地址,避免请求失败。
  • 服务器端无需注册IHelloWorldClient,保持DI容器的简洁性。

内容的提问来源于stack exchange,提问作者Daniel Arkley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:12:36