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

如何声明带不同泛型返回类型的泛型方法?接口改造求助

Refactoring IBlueFinApiClient to Support Generic Requests & Responses

Got it, let's work through this together. The goal is to make your client flexible enough to handle different request types while returning their matching response types, all while keeping type safety intact. Here's a straightforward, scalable solution:

First, create base classes to enforce a common contract for all your API requests and responses. This adds consistency and makes your code easier to maintain:

// Base class for all BlueFin API requests
public abstract class BlueFinApiRequestBase { }

// Base class for all BlueFin API responses
public abstract class BlueFinApiResponseBase { }

Update your existing request/response types to inherit from these bases:

public class BlueFinDecryptRequest : BlueFinApiRequestBase
{
    // Your existing request properties here
    public string EncryptedPayload { get; set; }
}

public class BlueFinDecryptResponse : BlueFinApiResponseBase
{
    // Your existing response properties here
    public string DecryptedData { get; set; }
}

2. Refactor the Interface with Generic Methods

Modify your IBlueFinApiClient to include a generic method that works with any valid request/response pair. You can also keep the original DecryptAsync method for backward compatibility:

public interface IBlueFinApiClient
{
    // Generic method for all request/response combinations
    Task<TResponse> SendRequestAsync<TRequest, TResponse>(TRequest request)
        where TRequest : BlueFinApiRequestBase
        where TResponse : BlueFinApiResponseBase, new();

    // Optional: Preserve original method to avoid breaking existing code
    default Task<BlueFinDecryptResponse> DecryptAsync(BlueFinDecryptRequest request)
    {
        return SendRequestAsync<BlueFinDecryptRequest, BlueFinDecryptResponse>(request);
    }
}

Key Notes:

  • The where constraints ensure only valid request/response types (inheriting from your base classes) can be used.
  • The new() constraint on TResponse lets you safely instantiate the response type if deserialization returns null.

3. Implement the Generic Client

Here's how to build the client to handle generic requests, using HttpClient for POST calls and mapping request types to their API endpoints:

public class BlueFinApiClient : IBlueFinApiClient
{
    private readonly HttpClient _httpClient;
    private readonly Dictionary<Type, string> _endpointMappings = new()
    {
        { typeof(BlueFinDecryptRequest), "/api/v1/decrypt" },
        { typeof(BlueFinEncryptRequest), "/api/v1/encrypt" }, // Example new request type
        // Add more endpoint mappings as you add new request types
    };

    public BlueFinApiClient(HttpClient httpClient)
    {
        _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
    }

    public async Task<TResponse> SendRequestAsync<TRequest, TResponse>(TRequest request)
        where TRequest : BlueFinApiRequestBase
        where TResponse : BlueFinApiResponseBase, new()
    {
        // Look up the correct endpoint for the request type
        if (!_endpointMappings.TryGetValue(typeof(TRequest), out var endpoint))
        {
            throw new InvalidOperationException($"No endpoint configured for request type {typeof(TRequest).Name}");
        }

        // Serialize request to JSON
        var jsonRequest = JsonSerializer.Serialize(request);
        var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");

        // Send POST request and handle response
        var httpResponse = await _httpClient.PostAsync(endpoint, content);
        httpResponse.EnsureSuccessStatusCode(); // Throws if HTTP error occurs

        // Deserialize response to the generic type
        var jsonResponse = await httpResponse.Content.ReadAsStringAsync();
        return JsonSerializer.Deserialize<TResponse>(jsonResponse) ?? new TResponse();
    }
}

4. Usage Example

Now you can easily send different types of requests with their matching responses:

// Initialize the client (use DI in production code)
var httpClient = new HttpClient { BaseAddress = new Uri("https://your-bluefin-api.com") };
var client = new BlueFinApiClient(httpClient);

// Send a decrypt request (using original or generic method)
var decryptRequest = new BlueFinDecryptRequest { EncryptedPayload = "your-encrypted-data" };
var decryptResponse = await client.DecryptAsync(decryptRequest);
// OR
var decryptResponseGeneric = await client.SendRequestAsync<BlueFinDecryptRequest, BlueFinDecryptResponse>(decryptRequest);

// Send a new encrypt request (example)
var encryptRequest = new BlueFinEncryptRequest { DataToEncrypt = "sensitive-data" };
var encryptResponse = await client.SendRequestAsync<BlueFinEncryptRequest, BlueFinEncryptResponse>(encryptRequest);

This approach keeps your code clean, type-safe, and ready to scale as you add more API endpoints.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:09:23