2

I have an application interface that uses http post/get using xml messages. The interfaceing system returns a message with result codes and the data requested. The result codes are 3 parts, code and subcode grouped by type (login, request...). Some code/subcodes are messages such as login successfull, others are exceptions such as invalid login or invalid message request.

I am trying to find a way to process the result codes and throw an exception with the message if needed. If result code is informational only, just apply the message on my return message to the api consumer. I am looking at the chain of responsibility, but running into brain block trying to work through it.

Sample codes
Type....Code..Subcode....Description
Login...0.....0..........Request successful
Login...0.....nn.........Login successful. “nn” days left until expiry
Login...21....1..........Login failed. (Userid/password wrong).
Login...21....4..........Already logged in
Login...21....5..........System resources unavailable. Fails to allocate a security object
Request.50....2..........service Invalid syntax
Request.50....3..........service Invalid attributes
Request.50....4..........service Batch file already exists

Result message with result codes (code, subcode):
loginmanagerresult 0, 0 is informational, all good
loginresult 0, 24855 is account good, no exipration
if loginresult had 1, 2, throw exception account locked out

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

I have the objects deserialized into the following: that cannot be changed, extended\inherited, but no additional properties\functions.

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


}
longday
  • 4,075
  • 4
  • 28
  • 35

1 Answers1

0

What you're trying to implement is a "pattern matching" mechanism, Chain of Responsibility pattern is kind of another name for the same thing in OOP. There is no built-in way in C# to do structural pattern matching, though you can look around on SO or somewhere else, there are some generic ideas.

If this is just a one-off thing you can try to just make a list of rules, which would look like pairs of (Predicate, Action). Then you Match method will go through the rules one by one, and the first rule with the Predicate returning true is a match and its Action is executed.

Why this may be better than a Chain of Responsibility? Well, you don't need many additional objects, you can use anonymous lambdas to specify predicates and actions, and then you rule list will just fit in one page of code, will be easy to read, change, review.

A quick example, which can be further improved is following. When you will add more rules you can further improve readability by extracting some common predicates or parts of predicates and some actions or parts of actions into named delegates.

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");
}
Community
  • 1
  • 1
Massimiliano
  • 16,770
  • 10
  • 69
  • 112