能否在Blazor Web App中结合具体实现与Refit复用同一服务?
解决方案
你可以通过两种简洁的方式实现共用IHelloWorld接口的需求,无需大量重复代码:
方案一:继承接口+DI映射
- 调整Refit客户端接口,让它直接继承
IHelloWorld,并在方法上添加Refit特性(用new关键字明确隐藏基类方法,避免编译器警告):
// 共用接口 public interface IHelloWorld { Task<string> GetGreetingAsync(); } // Refit客户端接口 public interface IHelloWorldClient : IHelloWorld { [Get("/api/helloworld/greeting")] new Task<string> GetGreetingAsync(); }
- 分别配置两端的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
相关产品推荐
相关产品推荐

