如何避免使用第三方Web服务重复代码 - 不使用动态?

Zoh*_*led 2 c# generics dynamic

我正在使用第三方Web服务,其中所有方法都具有以下签名:

SomeResponseClass SomeMethod(SomeRequestClass request)
Run Code Online (Sandbox Code Playgroud)

每个方法都有自己的请求类和它自己的响应类.然而,所有请求都有一些共同点,并且所有响应都有共同点.

每个请求类都有一些用于标识的属性:username并且token,每个响应类都有一些属性来指示是否存在错误:statuserror.

我正在寻找一种优雅的方法来创建一个实例化我的请求的方法 - 这样我就不必在调用服务的每个方法中重复自己.由于我无法更改类,并且没有所有类的通用接口或基类,我找到的唯一解决方案是使用dynamic:

private T CreateRequest<T>() where T : new()
{
    if(string.IsNullOrEmpty(_Token))
    {
        Login();
    }
    // this has to be dynamic for the next 2 rows to pass compilation.
    dynamic request = new T();
    request.username = _UserName;
    request.token = _Token;
    return (T)request;
}
Run Code Online (Sandbox Code Playgroud)

类似于从服务响应填充我自己的实体:

// response have to be dynamic for getting the error and status properties
private static T CreateServiceResponse<T>(dynamic response) where T : ServiceResponse, new()
{
    T result = new T();
    result.Error = (response == null) ? "Service response is null" : response.error;
    result.Status = (response == null) ? -1 : response.status;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

(这个方法在我用来填充我的实体(全部派生自来自ServiceResponse)的每个方法中都使用来自服务响应的数据.)

有没有办法在不使用的情况下做这样的事情dynamic?对我来说,有点像使用肮脏的黑客......

如果我能以某种方式"注入"所有请求实现的通用接口和所有响应实现的通用接口我可以使用简单的泛型,但我想这是不可能的,或者是它?

Sef*_*efe 5

当您使用visual studio创建的服务引用时,所有生成的类都标记为partial.这意味着您可以使用自己的代码扩展它们.在您的情况下,这将是一个提供重复属性的接口.您可以将该接口用作通用约束.

首先创建公共接口.为简单起见,您可以使用与服务引用中定义的公共属性相同的名称和类型:

interface IRequest {
    string username { get; set; }
    string token { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建一个代码文件,并在与服务引用相同的命名空间中为每个服务请求类(具有相同名称)定义一个分部类.每个类都实现了您的接口:

partial class SomeRequestClass : IRequest {}
Run Code Online (Sandbox Code Playgroud)

选择相同的属性名称和类型后,您无需专门实现该接口.

最后,您使用通用约束:

private T CreateRequest<T>() where T : IRequest, new()
{
    if(string.IsNullOrEmpty(_Token))
    {
        Login();
    }
    T request = new T();
    request.username = _UserName;
    request.token = _Token;
    return request;
}
Run Code Online (Sandbox Code Playgroud)