处理从外部系统查找结果代码 - 如果需要,抛出异常

时间:2012-05-17 19:35:58

标签: c# design-patterns exception-handling

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

我正在尝试找到一种处理结果代码的方法,并在需要时使用该消息抛出异常。如果结果代码仅供参考,只需将我的返回消息上的消息应用于api使用者。我正在研究责任链,但遇到脑力障碍试图通过它。

示例代码
键入.... Code..Subcode ....说明
登录... 0 ..... 0 ..........申请成功
登录... 0 ..... nn .........登录成功。 “nn”天,直到到期为止 登录... 21 .... 1 ..........登录失败。 (用户名/密码错误)。
登录... 21 .... 4 ..........已登录
登录... 21 .... 5 ..........系统资源不可用。无法分配安全对象
Request.50 .... 2 .......... service语法无效
Request.50 .... 3 .......... service无效的属性
Request.50 .... 4 .......... service批处理文件已存在

带结果代码的结果消息(代码,子代码):
loginmanagerresult 0,0是信息性的,都很好 loginresult 0,24855是账号好,没有exipration
如果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; }
    }


}

1 个答案:

答案 0 :(得分:0)

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

如果这只是一次性的事情,你可以尝试制作一个规则列表,这些规则看起来像是一对(谓词,动作)。然后,Match方法将逐个执行规则,并且Predicate返回true的第一个规则是匹配并执行其Action。

为什么这可能比责任链更好?好吧,你不需要很多额外的对象,你可以使用匿名lambdas来指定谓词和动作,然后你的规则列表就会适合一页代码,很容易阅读,更改,复习。

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

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");
}