class - C# How to tell if an object implements a particular method -
so have number of different potential object can output data (strings). want able do, run generic output.writeline function, potential arguments define want outputted to. i've got code -
//defined in static class const public enum out : int { debug = 0x01, main = 0x02, code = 0x04 }; static class output { private static list<object> retrieveoutputmechanisms(const.out output) { list<object> result = new list<object>(); #if debug if (bitmask(output, const.out.debug)) result.add(1);//console); //i want add console here, static #endif if (bitmask(output, const.out.main)) if (program.mainform != null) result.add(program.mainform.box); if (bitmask(output, const.out.code)) if (program.code!= null) result.add(program.code.box); return result; } public static void writeline(color color, string str, const.out output = const.out.debug & const.out.main) { console.writeline( list<object> writers = retrieveoutputmechanisms(output); foreach (object writer in writers) writer.writeline(str, color); } } the point of this, output destinations not existent, on forms may or may not exist when these calls called. idea determine ones you're trying print to, determine if exists, add list of things printed to, loop through , print of them if implement "writeline" method.
the 2 problems i've come across, are
- that console static class, , can't (as far knowledge goes) added object list.
i don't know how can assert objects in list define writeline, , cast them apply more 1 base type. assuming can console work in scheme, obvious problem, not of same base type actual boxes, also, if had wasnt box, lovely
foreach (object writer in writers) .writeline(str, color)
so wouldn't have individually cast them.
the bigger reason don't writeline retrieveoutputmechanisms function, want cover more writeline, means need copy bitmask code each function.
edit: realise adding public properties program bad idea, if know how can avoid (the necessity coming needing able access writeline-able form objects come , go, anywhere), means please elaborate.
one way use action (a delegate) , store in list. work console , other class can write lambda (or 2.0 delegate) map output variables right parameters in called method. there no need casting. work this:
(this assumes using c# 3.5 or later can in 2.0 , on using delegates)
static class output { private static list<action<string, color>> retrieveoutputmechanisms(const.out output) { list<action<string, color>> result = new list<string, color>(); #if debug if (bitmask(output, const.out.debug)) result.add((s, c) => console.writeline(s, c)); //i want add console here, static #endif if (bitmask(output, const.out.main)) if (program.mainform != null) result.add((s, c) => program.mainform.box.writeline(s, c)); if (bitmask(output, const.out.code)) if (program.code!= null) result.add((s, c) => program.code.box.writeline(s, c)); return result; } public static void writeline(color color, string str, const.out output = const.out.debug & const.out.main) { var writers = retrieveoutputmechanisms(output); foreach (var writer in writers) writer(str, color); } } (edit add)
you change more allow classes "register" able writing specific "output mechanism" in output class itself. make output singleton (there arguments against doing better sticking public static variables in main program purpose). here example more significant changes original class:
public sealed class output { private dictionary<out, action<string, color>> registeredwriters = new dictionary<out, action<string, color>>(); public static readonly output instance = new output(); private void output() { } // empty private constructor instance cannot created. public void unregister(out outtype) { if (registeredwriters.containskey(outtype)) registeredwriters.remove(outtype); } // assumes caller not combine flags outtype here public void register(out outtype, action<string, color> writer) { if (writer == null) throw new argumentnullexception("writer"); if (registeredwriters.containskey(outtype)) { // throw exception, such invalidoperationexception if don't want // allow different writer assigned once 1 has been. registeredwriters[outtype] = writer; } else { registeredwriters.add(outtype, writer); } } public void writeline(color color, string str, const.out output = const.out.debug & const.out.main) { bool includedebug = false; #if debug includedebug = true; #endif foreach (var outtype in registeredwriters.keys) { if (outtype == const.out.debug && !includedebug) continue; if (bitmask(output, outtype)) registeredwriters[outtype](str, color); } } } then elsewhere in program, such in form class, register writer, do:
output.instance.register(const.out.main, (s, c) => this.box.writeline(s, c)); when form unloaded can do:
output.instance.unregister(const.out.main); then way not use singleton. have more 1 output instance different purposes , inject these other classes. instance, change constructor main form accept output parameter , store object variable later use. main form pass on child form needs it.
Comments
Post a Comment