2

我有一个使用 xml 消息使用 http post/get 的应用程序界面。接口系统返回带有结果代码和请求数据的消息。结果代码分为 3 部分,代码和按类型分组的子代码(登录、请求...)。一些代码/子代码是登录成功等消息,其他是无效登录或无效消息请求等异常。

我正在尝试找到一种方法来处理结果代码并在需要时抛出带有消息的异常。如果结果代码仅供参考,只需将我的返回消息中的消息应用到 api 使用者即可。我正在查看责任链,但在试图通过它时遇到了脑块。

示例代码
类型....代码..子代码....描述
登录...0.....0..........请求成功
登录...0.....nn .........登陆成功。距离到期还有“nn”天
登录...21....1..........登录失败。(用户名/密码错误)。
登录...21....4........已经登录
登录...21....5..........系统资源不可用。分配安全对象失败
Request.50....2........service Invalid syntax
Request.50....3..........service Invalid attributes
Request. 50....4........服务批处理文件已存在

带有结果代码(代码、子代码)的结果消息:
loginmanagerresult 0, 0 是信息性的,all good
loginresult 0, 24855 是帐户好,
如果 loginresult 有 1、2 则不会过期,抛出异常帐户被锁定

<?xml version="1.0" encoding="UTF-8"?>  
    <loginmanagerresult sessionname="ALBHMROC9040RL1" code="0" subcode="0">
        <loginresult code="0" subcode="24855" sectoken="f1044f0aaad65ef2e28d4edc0663716f00000000"></loginresult>
    </loginmanagerresult>

我将对象反序列化为以下内容:无法更改、扩展\继承,但没有其他属性\函数。

public class LoginResult
{

    private string code = "";
    [XmlAttribute("code")]
    public string Code
    {
        get { return code; }
        set { code = value; }
    }

    private string subCode = "";
    [XmlAttribute("subcode")]
    public string SubCode
    {
        get { return subCode; }
        set { subCode = value; }
    }

    private string secToken = "";
    [XmlAttribute("sectoken")]
    public string SecToken
    {
        get { return secToken; }
        set { secToken = value; }
    }

}

[XmlRoot("loginmanagerresult")]
public class LoginManagerResult
{

    private string sessionName = "";
    [XmlAttribute("sessionname")]
    public string SessionName
    {
        get { return sessionName; }
        set { sessionName = value; }
    }

    private string code = "";
    [XmlAttribute("code")]
    public string Code
    {
        get { return code; }
        set { code = value; }
    }

    private string subCode = "";
    [XmlAttribute("subcode")]
    public string SubCode
    {
        get { return subCode; }
        set { subCode = value; }
    }

    private LoginResult loginResult = null;
    [XmlElement("loginresult", IsNullable = true)]
    public LoginResult LoginResult
    {
        get { return loginResult; }
        set { loginResult = value; }
    }

    private QueryCapabilitiesResult queryCapabilitiesResult = null;
    [XmlElement("querycapabilitiesresult", IsNullable = true)]
    public QueryCapabilitiesResult QueryCapabilitiesResult
    {
        get { return queryCapabilitiesResult; }
        set { queryCapabilitiesResult = value; }
    }

    private GetMotdResult getMotdResult = null;
    [XmlElement("getmotdresult", IsNullable = true)]
    public GetMotdResult GetMotdResult
    {
        get { return getMotdResult; }
        set { getMotdResult = value; }
    }

    private LogOutResult logOutResult = null;
    [XmlElement("logoutresult", IsNullable = true)]
    public LogOutResult LogOutResult
    {
        get { return logOutResult; }
        set { logOutResult = value; }
    }


}
4

1 回答 1

0

您要实现的是“模式匹配”机制,责任链模式是 OOP 中同一事物的另一种名称。C# 中没有内置的方法来进行结构模式匹配,尽管您可以在 SO 或其他地方查看,但有一些通用的想法

如果这只是一次性的事情,您可以尝试制作一个规则列表,看起来像是成对的(谓词,动作)。然后你的 Match 方法会一个一个的遍历规则,第一个 Predicate 返回 true 的规则是匹配的,它的 Action 会被执行。

为什么这可能比责任链更好?好吧,您不需要很多额外的对象,您可以使用匿名 lambda 来指定谓词和操作,然后您的规则列表将恰好适合一页代码,易于阅读、更改和审查。

下面是一个可以进一步改进的快速示例。当您将添加更多规则时,您可以通过将一些常见谓词或部分谓词以及一些操作或部分操作提取到命名委托中来进一步提高可读性。

public class LoginResult
{
    public string Code { get; set; }
    public string SubCode { get; set; }
    public string SecToken { get; set; }
}

public static IDictionary<Predicate<LoginResult>, Func<LoginResult, string>> rules =
    new Dictionary<Predicate<LoginResult>, Func<LoginResult, string>>
        {
            { lr => lr.Code == "0" && lr.SubCode != "0", result => "Login successful, days left till expiration: " + result.SubCode },
            { lr => lr.Code == "0", _ => "Login successful" },
            { lr => lr.Code == "21", _ => ThrowInvalidOperation("Login failed. (Userid/password wrong).") },
        };

static string ThrowInvalidOperation(string message)
{
    throw new InvalidOperationException(message);
}

static string Match(LoginResult result)
{
    foreach (var rule in rules)
    {
        if (rule.Key(result))
        {
            return rule.Value(result);
        }
    }

    throw new ArgumentException("Matching rule not found", "result");
}
于 2012-09-01T04:00:08.510 回答