.net 多对象类型的C#重复逻辑,泛型的候选者?

rks48beu  于 2022-12-30  发布在  .NET
关注(0)|答案(2)|浏览(93)

我的代码中有多个 GetResponse 函数,每个函数的返回类型、传递的单个参数和调用SOAP接口的单行代码不同。
我不知道如何变成泛型方法,也不知道它是否有意义。我在这里使用DRY原则。
我无法更改对象类型,因为它们是使用连接的服务类型(WSDL)自动构建的。
我想我需要以某种方式标记在调用该方法时要使用哪个SOAP调用。
任何帮助都将不胜感激。
以下是两个示例定义:

private GetAccountInfoResponse GetResponse(GetAccountInfoRequest req) {...}

    private CleanseAddressResponse GetResponse(CleanseAddressRequest req) {...}

下面是GetAccountInfos的完整代码:

private GetAccountInfoResponse GetResponse(GetAccountInfoRequest req)
    {
      MethodBase m = MethodBase.GetCurrentMethod();
      string source = $"{m.ReflectedType.Name}.{m.Name}";

      SwsimV111Soap swsim = swsimFactory.CreateChannel();
      GetAccountInfoResponse resp = null;
      int retry = 0;

      if (Logging.GetLevelFromString(ConfigSettings.LogLevel) > LogLevels.Information)
        ReportStatus(LogLevels.Debug, source, $"SWSIM req: {SupportClasses.XmlConvert.SerializeObject(req)}");

      while (resp == null && retry < 1)
      {
        try
        {
          resp = swsim.GetAccountInfo(req); //<= call changes with each (req) type
          _authToken = resp.Authenticator;
        }
        catch (FaultException ex)
        {
          if (ex.Message.ToLower().Contains("converstion out-of-sync"))
          {
            ClearAuthState();
            req.Item = GetCredsType();
          }
          else
          {
            msg = $"Call Fault: {Misc.ParseException(ex)}";
            break; //Force end of loop
          }
        } // catch (FaultException ex)
        catch (Exception ex)
        {
          msg = $"Call Error: {Misc.ParseException(ex)}";
          break; //Force end of loop
        }
        retry++;
      } //while (resp == null && retry < 2)

      if (resp != null)
      {
        if (Logging.GetLevelFromString(ConfigSettings.LogLevel) > LogLevels.Information)
          ReportStatus(LogLevels.Debug, source, $"SWSIM resp: {SupportClasses.XmlConvert.SerializeObject(resp)}");
      }
      else ReportStatus(LogLevels.Error, source, $"Fault Exception: {msg}");
      return resp;
    }
oxcyiej7

oxcyiej71#

典型的解决方案是定义一个接口,并让这些对象类型中的每一个实现该接口。

d6kp6zgx

d6kp6zgx2#

您可以结合使用泛型和回调来执行实际的方法调用。
给定以下类型声明:

public class Request {}
public class Response {}

public class GetAccountInfoResponse : Response { }
public class CleanseAddressResponse : Response { }
public class GetAccountInfoRequest : Request { }
public class CleanseAddressRequest: Request { }

public class SwsimV111Soap
{
    public GetAccountInfoResponse GetAccountInfo(GetAccountInfoRequest req) => new GetAccountInfoResponse();

    public CleanseAddressResponse GetCleanseAddress(CleanseAddressRequest req) => new CleanseAddressResponse();
}

这就是你如何编写你的方法,省去所有不相关的东西,你可以添加进去:

private TResp GetResponse<TReq, TResp>(TReq req, Func<SwsimV111Soap, TReq, TResp> func) where TReq : Request where TResp : Response
{
    SwsimV111Soap swsim = new SwsimV111Soap(); // Use your factory here
    // Do the actual call using the passed callback function
    TResp resp = func(swsim, req);

    return resp;
}

我们使用泛型类型作为请求类型和响应类型,然后我们还期望一个函数作为参数,该函数对服务类型进行操作,并且也使用请求和响应类型。
在方法内部,我们用服务示例和请求示例调用函数,它将返回响应示例。
用法如下:

private void button1_Click(object sender, EventArgs e)
{
    GetAccountInfoResponse resp1 = GetResponse(new GetAccountInfoRequest(), (s, r) => s.GetAccountInfo(r));
    CleanseAddressResponse resp2 = GetResponse(new CleanseAddressRequest(), (s, r) => s.GetCleanseAddress(r));
}

我们可以使用lambda表达式语法轻松地创建执行实际调用的预期函数。

相关问题