design patterns - C# Open but closed principle for parsing -
what should use custom parsing provide extensibility without having inherit? in other words, looking iformatprovider (used output) equivalent parsing of custom object.
opposite of following code:
var str = string.format(new myformatprovider(), "{0:custom}", obj); where myformatprovider implements iformatprovider
open/closed says new or changed behaviors should add-able without modifying existing code. in oop, that's done either inheritance or interfaces (a special kind of "inheritance").
you'd need little more specific problem domain more specific answer, example using interfaces like:
interface iobjectparser { object parse(object obj, propertyname string); } class reflectionparser : iobjectparser { public object parse(object obj, propertyname string) { return obj.gettype().getproperty(propertyname).getmethod().invoke(obj); } } object parsedvalue = new reflectionparser().parse(new myclass(), "myproperty"); then, if wanted added new type of parser:
class databaseparser : iobjectparser { public object parse(object obj, propertyname string) { return executequery( --note potential sql injection string.format("select {1} {0} id = @id", obj.gettype().name, propertyname), ((dynamic)o).id ); } } object parsedvalue = new databaseparser(new myclass(), "columnname"); this isn't particular open/closed, since brought iformatprovider uses technique tunnel variable number of parameters in format string while still adhering strong typing.
i'm not sure if there's canonical name it, refer "stringly typed" (you can same array of objects, etc. - using string common , makes pun). can see type of api in things javascript's window.open windowfeatures , mvc's htmlhelpers htmlattributes (which uses anonymous type same effect), i'd it's anti-pattern in cases since it's breaks liskov substitution principle, have it's niche uses.
iformatprovider (technically, icustomformatter part, , iformatprovider factory) has support unknown number of possible formats. that, tunnels custom formatting instructions after ":" - it's expected appropriate icustomformatter know values.
an example of in iobjectparser case like:
class bytearrayparser : iobjectparser { public object parse(object obj, propertyname string) { var bytes = obj byte[]; // we've tunneled multiple parameters in propertyname string var nameparameters = propertyname.split(":"); // note we've lost our strong typing, , coupled ourselves propertyname format int index = int.parse(nameparameters[0]); string readastype = nameparameters[1]; using (var ms = new memorystream(bytes)) using (var br = new binaryreader(ms)) { ms.position = index; switch (readastype) { case "float": return br.readsingle(); case "int": return br.readint32(); case "string" // can have yet parameter in special cases if (nameparameters.length > 2) { // it's ascii string int stringlength = int.parse(nameparameters[2]); return encoding.ascii.getstring(br.readbytes(stringlength)); } else { // it's binaryreader's native length-prefixed string return br.readstring(); } default: // don't know type throw new argumentoutofrangeexception("type"); } } } } when using class, have specially format propertyname in way can discovered through documentation (just string.format).
// note again, have know bytearrayparser's specific format , lose strong typing object parsedintvalue = new bytearrayparser().parse(mybytes, "4:int"); object parsedsinglevalue = new bytearrayparser().parse(mybytes, "4:float"); object parsedstringvalue = new bytearrayparser().parse(mybytes, "4:string"); object parsedasciistringvalue = new bytearrayparser().parse(mybytes, "4:string:15");
Comments
Post a Comment