Sorry for not so discrptive title, if someone wants to change it go ahead. Also note I have already asked a question about this kind of thing but this one is more about how you would attack it because my attack just doesn't seem to feel right.
I am having a problem with building a string up to send to an OLE object in the correct order using the polymorphism method in the other question.
The OLE object can only take and receive a string, so what I am doing is building a wrapper around all the common commands and providing a more .NET feel for them.
The problem I ran into very fast was some of the commands that my wrapper had to send where very long and had optional bits which then suddenly turned a method that was only setting a name into a big string building method with if's just to set a name and of course this happens all over the place because there are a lot of commands.
Now in order to have a good wrapper I would like to be able to wrap up the string building process so that I move the string building logic away from the wrapper itself and into a builder object.
I tried to attack this by using polymorphism which works well when I have a builder object class designed just for building that one type of command string. See other post for details.
Sorry for the long post I will cut to the chase now.
The main problem is that there is a lot of command strings that have to be built up which means more builder objects.
So I would really like to have a generic string builder that can build a string from any list of commands but the catch is they have to be in the correct order even if the user sets them in the wrong order.
How would you approach this?
-
I think you're over complicating things and will end up creating too many classes.
I'd look at the problem as less a string-building one and more of how you'd present a nice interface to a .net caller. Just because there are lots of possible arguments doesn't mean you need to create lots of classes for them, at least if the possible variations within each argument aren't very sophisticated, ie if the value is either there or it's not, and has optional units. Then you get yourself into this mess of needing to know the order the parts of the command need to have, etc.
Probably I'd create a class for the possible arguments of the command, let a caller set whichever ones they like, and have that class responsible for generating the string in one big (ugly?) string concatenation.
For example I'd start with something like this, and as you go I'd add methods where it makes sense to refactor a little of the string concatenation, depending on the similarity of the different parts of the command.
class CommandArgs { private double? _Position_x = null; private double? _Position_y = null; private String _Position_units = null; private double? _Width = null; private String _Width_units = null; private double? _Height = null; private String _Height_units = null; // maybe there's a better tuple-like type for this. public double[] Position { set { if (value.length != 2) throw new ArgumentException("argh!"); _Position_x = value[0]; _Position_y = value[1]; } } public string Position_Units { set { _Position_Units = value; } } public double Width set { _Width = value; } } public double Height set { _Height = value; } } public string Width_Units set { _Width = value; } } public string Height_Units set { _Height = value; } } // .... public override string ToString() { return ( _Position_x != null ? string.Format(" Position ({0},{1})",_Position_x, _Position_y ) : "" ) + ( _Height != null ? string.Format(" Height {0}") + ( _Height_Units != null ? string.Format(" Units {0}", _Height_Units) : "" ) + ( _Width != null ? string.Format(" Width {0}") + ( _Width_Units != null ? string.Format(" Units {0}", _Width_Units) : "" ) // ... ; } }
If you prefer you might like to make methods instead of properties, so you can set the value and units at the same time.
I'd probably refactor that with the following methods immediately:
private string FormatUnits(string units) { return units == null ? "" : string.Format(" Units {0}", units); } private string FormatSingleValueArgument(string argName, object argValue, string units) { if (argValue == null) return ""; return string.Format(" {0} {1}", argName, argValue) + FormatUnits(units); }
making that ToString() look like this:
return ( _Position_x != null ? string.Format(" Position ({0},{1})",_Position_x, _Position_y ) : "" ) + FormatSingleValueArgument("Height", _Height, _Height_Units) + FormatSingleValueArgument("Width", _Width, _Width_Units) // ... ;
then perhaps do a similar method for Position-like arguments, if there are several of them.
Nathan W : Is was trying to avoid having to do a heap of if statements and null checking, the example you gave will work for this case but it will still get very complicated with some of the other statements that I have wrap up.Nathan W : I really don't see a problem in having lots of classes as long as they are in name spaces.
0 comments:
Post a Comment