Reputation: 369
I have a class that handles incoming over-the-air messages and parses them. Depending on the output of the command, I need to handle some UI modifications such as highlighting labels, adding text to textboxes etc. The first option I was using is:
void IncomingMessageIfStatements(Message msg, Host host)
{
byte resp;
if (ParseMessageOptionOne(msg, out resp))
{
// Do some windows form stuff
}
else if (ParseMessageOptionTwo(msg, out resp))
{
// Do some windows form stuff
}
else if (ParseMessageOptionThree(msg, out resp))
{
// Do some windows form stuff
}
}
private bool ParseMessageOptionOne(Message msg, out byte resp)
{
throw new NotImplementedException();
}
private bool ParseMessageOptionTwo(Message msg, out byte resp)
{
throw new NotImplementedException();
}
private bool ParseMessageOptionThree(Message msg, out byte resp)
{
throw new NotImplementedException();
}
This works, but I will have more else if
statements and it could get ugly. The next way I looked at doing is:
void IncomingMessageSwitchStatements(Message msg, Host host)
{
byte resp = 0;
byte someByte = 0;
bool output = false;
switch (someByte)
{
case 1:
output = ParseMessageOptionOne(msg, out resp);
break;
case 2:
output = ParseMessageOptionTwo(msg, out resp);
break;
case 3:
output = ParseMessageOptionThree(msg, out resp);
break;
default:
//handle exception here
break;
}
if (output && resp == 0x01)
{
UpdateUiFromHere();
}
}
private void UpdateUiFromHere()
{
// handle UI updates here
}
This looks much cleaner and works as intended. But then I started looking at Dictionary<byte, Func<bool>>
and thought maybe that was a better approach to solving the handling of multiple conditions incoming (possibly 20).
Any suggestions on the best practice I should go for, given whats needed?
Upvotes: 2
Views: 4649
Reputation: 10889
Another alternative would be to use LINQ to loop through a list of delegate methods, and short-circut as soon as a true
condition is found.
private delegate bool ParseMessageWrapper(Message msg, out byte resp);
void IncomingMessageSwitchStatements(Message msg, Host host)
{
byte resp = 0;
bool output = false;
var parseMethods = new List<ParseMessageWrapper>()
{
new ParseMessageWrapper(ParseMessageOptionOne),
new ParseMessageWrapper(ParseMessageOptionTwo),
new ParseMessageWrapper(ParseMessageOptionThree)
};
output = parseMethods.Any(func => func.Invoke(msg, out resp));
if (output && resp == 0x01)
{
UpdateUiFromHere();
}
}
Upvotes: 0
Reputation: 1322
You can as well change the method signature of ParseMessageOptionOne, ParseMessageOptionTwo, ParseMessageOptionThree to return a response object that encapsulates output, response and use Func built-in delegate to store methods:
public struct ParseResponse
{
public bool output;
public byte response;
}
class ParseOptions
{
Func<Message, ParseResponse>[] options = null;
public ParseOptions()
{
options = new Func<Message, ParseResponse>[]{
ParseMessageOptionOne,
ParseMessageOptionTwo,
ParseMessageOptionThree
};
}
public void IncomingMessageSwitchStatements(Message msg, Host host)
{
byte someByte = 2;
var response = options[someByte](msg);
if (response.output && response.response == 0x01)
{
//UpdateUiFromHere();
}
}
private ParseResponse ParseMessageOptionThree(Message msg)
{
return new ParseResponse { output = true };
}
}
Upvotes: 0
Reputation: 7163
I would move the parsing to inside the Message class itself.
Options option = msg.GetOption();
I would also make an enum for all your options:
public enum Options {
One,
Two,
None
}
Then write your code to make use of that however you need to...
if (option == Options.One)
// or
switch(option)
// etc.
Hard to recommend more since I can't tell what UpdateUiFromHere()
does since it takes no parms...but this should be some good food for thought.
Upvotes: 0
Reputation: 30813
Since what you want to do is to "Call method with the same signature based on index number", you could use delegate
and list them in a Dictionary
(or in a List
if the index starts from 0
) to make your intention clear.
public delegate bool ParseMessage(Message msg, out byte resp);
And then list it using Dictionary
:
Dictionary<byte, ParseMessage> parser = new Dictionary<byte, ParseMessage>(){
{1, new ParseMessage(ParseMessageOptionOne)},
{2, new ParseMessage(ParseMessageOptionTwo)},
{3, new ParseMessage(ParseMessageOptionThree)}
};
or using List
List<ParseMessage> parser = new List<ParseMessage>(){
new ParseMessage(ParseMessageOptionOne),
new ParseMessage(ParseMessageOptionTwo),
new ParseMessage(ParseMessageOptionThree)
};
And call it like this:
bool result = parser[resp](msg, out resp); //dictionary
bool result = parser[resp-1](msg, out resp); //list
Upvotes: 3