简体   繁体   English

C#中具有两个通用参数的通用方法

[英]Generic method in C# with two generic parametres

I want to create generic method for this type of methods which take two type of generic values? 我想为这种类型的方法创建泛型方法,它采用两种类型的泛型值?

I dont want to make overload methods for auditing to doing the same redundant work. 我不想让审计的重载方法做同样的冗余工作。

public class UserProfile : IUserProfile
{
    private static void GetAudit(ChangePasswordRequest changePasswordRequest, ChangePasswordResponse changePasswordResponse,
        int memberId, RemoteEndpointMessageProperty endpointProperty)
    {
        string auditText = "ChangePassword Req:";
        auditText += Util.Serialize(changePasswordRequest).ToString(CultureInfo.InvariantCulture);
        auditText += "Res:";
        auditText += Util.Serialize(changePasswordResponse).ToString(CultureInfo.InvariantCulture);
        Audit.Add(AuditEventType.UpdatePassword, Severity.Normal, memberId,
            changePasswordRequest.TokenId,
            auditText,
            endpointProperty.Address, changePasswordRequest.IpAddress);
    }
    private static void GetAudit(LoadSupplierRequest loadSupplierRequest, LoadSupplierResponse loadSupplierResponse,int memberID,
        RemoteEndpointMessageProperty endpointProperty)
    {
        string auditText = "LoadSupplier Req:";
        auditText += Util.Serialize(loadSupplierRequest).ToString(CultureInfo.InvariantCulture);
        auditText += "Res:";
        auditText += Util.Serialize(loadSupplierResponse).ToString(CultureInfo.InvariantCulture);
        Audit.Add(AuditEventType.LoadSupplier, Severity.Normal, memberID, loadSupplierRequest.TokenId,
            auditText,
            endpointProperty.Address, loadSupplierRequest.IpAddress);
    }
}

Following are the structure of class and interface 以下是类和接口的结构

public class ChangePasswordResponse : IResponse
{
    /// <summary>
    ///     Gets or sets the status.
    /// </summary>
    /// <value>
    ///     The status.
    /// </value>
    [DataMember]
    public ChangePasswordResponseStatus Status { get; set; }

    /// <summary>
    ///     Gets or sets the error.
    /// </summary>
    /// <value>
    ///     The error.
    /// </value>
    [DataMember]
    public Error Error { get; set; }

    /// <summary>
    ///     Gets or sets the token identifier.
    /// </summary>
    /// <value>
    ///     The token identifier.
    /// </value>
    [DataMember]
    public string TokenId { get; set; }
}
public interface IResponse
{
    [DataMember]
    Error Error { get; set; }

    [DataMember]
    string TokenId { get; set; }
}

public interface IRequest
{
    /// <summary>
    ///     Gets or sets the ip address.
    /// </summary>
    /// <value>
    ///     The ip address.
    /// </value>
    [DataMember(IsRequired = true)]
    string IpAddress { get; set; }

    /// <summary>
    ///     Gets or sets the token identifier.
    /// </summary>
    /// <value>
    ///     The token identifier.
    /// </value>
    [DataMember(IsRequired = true)]
    string TokenId { get; set; }
}
[Serializable]
public class ChangePasswordRequest : IRequest
{
    /// <summary>
    ///     Gets or sets the old password.
    /// </summary>
    /// <value>
    ///     The old password.
    /// </value>
    [DataMember(IsRequired = true)]
    public string OldPassword { get; set; }

    /// <summary>
    ///     Gets or sets the new password.
    /// </summary>
    /// <value>
    ///     The new password.
    /// </value>
    [DataMember(IsRequired = true)]
    public string NewPassword { get; set; }

    /// <summary>
    ///     Gets or sets the ip address.
    /// </summary>
    /// <value>
    ///     The ip address.
    /// </value>
    [DataMember(IsRequired = true)]
    public string IpAddress { get; set; }

    /// <summary>
    ///     Gets or sets the token identifier.
    /// </summary>
    /// <value>
    ///     The token identifier.
    /// </value>
    [DataMember(IsRequired = true)]
    public string TokenId { get; set; }
}

Probably you should extract interfaces instead of using generics here: 可能你应该在这里提取接口而不是使用泛型

public interface IRequest {
  String TokenId {get;}
  String IpAddress {get;}
  ... 
} 

public interface IResponse {
  ...
} 

public class LoadSupplierResponse: IResponse {...}

public class ChangePasswordResponse: IResponse {...}

public class LoadSupplierRequest: IRequest {...}

public class ChangePasswordRequest: IRequest {...}

public static class Util {
  ...
  public static String Serialize(IRequest value) {...} 
  public static String Serialize(IResponse value) {...} 
} 

public class UserProfile : IUserProfile {
  private static void GetAudit(IRequest request, 
                               IResponse response,
                               int memberID,
                               RemoteEndpointMessageProperty endpointProperty) {
    string auditText = "LoadSupplier Req:";
    auditText += Util.Serialize(request).ToString(CultureInfo.InvariantCulture);
    auditText += "Res:";
    auditText += Util.Serialize(response).ToString(CultureInfo.InvariantCulture);
    Audit.Add(AuditEventType.LoadSupplier, 
              Severity.Normal, 
              memberID, 
              request.TokenId,
              auditText,
              endpointProperty.Address, 
              request.IpAddress);
  }
  ...
}

I had the exact same idea in mind as the answer from Dmitry. 我和Dmitry的回答完全相同。 I didn't see a response when I was composing mine. 当我写作我的时候,我没有看到回应。

private static void GetAudit<TRequest, TResponse>(TRequest request, TResponse response, int memberId, RemoteEndpointMessageProperty endpointProperty)
{
    var auditSB = new StringBuilder();
    auditSB.Append("Req:");
    auditSB.Append(Util.Serialize(request).ToString(CultureInfo.InvariantCulture));
    auditSB.Append("Res:");
    auditSB.Append(Util.Serialize(response).ToString(CultureInfo.InvariantCulture));

    if (request is ChangePasswordRequest)
    {
        // check if TResponse is ChangePasswordResponse
        // throw ArgumentException if TResponse is not right type

        var changePasswordRequest = TRequest as ChangePasswordRequest;
        Audit.Add(AuditEventType.UpdatePassword, Severity.Normal, memberId,
            changePasswordRequest.TokenId,
            auditSB.ToString(),
            endpointProperty.Address, changePasswordRequest.IpAddress);
    }
    else if (request is LoadSupplierRequest)
    {
        // check if TResponse is LoadSupplierResponse
        // throw ArgumentException if TResponse is not right type

        // do Auditing
    }
    else
    {
        throw new ArgumentException("Invalid Request type");
    }
}

I did this way: 我是这样做的:

private static void LogNormalAudit<TRequest, TResponse>(TRequest request, TResponse response,
        IRequest objRequest, int memberId, AuditEventType eventType)
    {
        bool isNormalSeverityOn = Convert.ToBoolean(ConfigurationSystem.SharedApiConfig["normal"]);
        if (!isNormalSeverityOn) return;
        var auditText = string.Format("Req: {0} |Rsp: {1}", Util.Serialize(request), Util.Serialize(response));
        Audit.Add(eventType, Severity.Normal, memberId, objRequest.TokenId, auditText, GetClientIp(),
            objRequest.IpAddress);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM