[Posted and mailed] [Tobias replied to me privately, then asked me to forward his reply here. Instead I will just keep it all quoted :-]
> -----Original Message----- > From: Tobias Oberstein [mailto:[EMAIL PROTECTED]] > Sent: Saturday, 2 February 2002 4:15 AM > To: [EMAIL PROTECTED] > Subject: Re: design patterns for "parameters" in ContractIDs > > > > It is not clear what you are asking. contract IDs are unique(ish) > > strings. For every known contract ID, there is a class ID, which > > uniquely identifies a component, as implemented in some source file > > (generally .c/cpp or .js) > > That has been clear to me - what wasn't clear to me from the beginning > is that different ContractIDs can be mapped to one CLSID, as > with > > @mozilla.org/uriloader/content-handler;1?type=text/plain > @mozilla.org/uriloader/content-handler;1?type=text/xml > @mozilla.org/uriloader/content-handler;1?type=text/jpeg > .. > > and still it's a mystery to me (even after reading the sources) how > in this particular case the single implementation (XPCOM class) behind > this CLSID gets information about the ?type=XXX it was > instantiated for. > > > > So all you need to do is register an xpcom component with > > the contract > > ID "@xyz.com/some-module/foobar;1?param1=small;param2=blue" > > and one for param1=big;param2=red and one for param1=big;param2=green > and so on .. what if param1 can take values from {0,1,2,3,... 2^32-1} It seemed to me from your original question that your data sets were fairly small. Thus, you may end up with 15-20 different components, but that may be fine. As you suggested, C++ templates could probably be used to do alot of that. You create a base class, and have a template define a sub-class, that both create a contract ID, and override an Init() virtual with the necessary "params". > > this is case 1.b.i in my statement, which is indeed sloppy and not > very precise by the way ;) > > > > Further, it should be acceptable that a client may _not_ resort > > > parameters like this: > > > > > > "@xyz.com/some-module/foobar;1?param2=blue;param1=small" > > > > No problem - that is a different, unknown string. > > well, no practical problem - though quite non-intuitive not to > be allowed to reorder _named_ parameters - but agreed.. its > practically irrelevant. > > > > > > 1. Are there established patterns of design to realize such stuff? > > > a) .. where there is one implementing class and the ContractID > > > parameters are used to initialize some member vars of the > > > implementing class > > > > The contract ID generally exists in a source file. One source file > > could implement many components. > > seems we're talking about different things. I tried to make the following > point: I don't want to write one implementation per parameter combination. > > I want to have one implementing class, taking the parameters either in > a constructor > > class MyClass : public ISomeIfc > { > MyClass(int param1, int param2); > } > > or have a Init(int param1, int param2) method _automatically_ called > with the values the client provided implicitely in the ContractID. > > I don't want to write code for: > > class MyClass_BlueBig; > class MyClass_BlueSmall; > class MyClass_RedBig; > ... > > > > > > > b) .. where there are multiple implementing classes and the > > > parameters are used to choose the appropriate implementation > > > > It is only ever done (as far as I know) using different contract IDs. > > Not params as such, but call it that if you like :) > > Well, they _look_ like parameters .. even if there are just opaque > ContractIDs. Agreed. > > > > > > > > i) .. and the different implementations are manually programmed > > > implementation classes > > > > Not sure what you are asking. > > This was ment versus C++ templates, which I look at as some kind > of "compiler written". > But this case is and was clear to me .. I just provided it in the list > to make this list kind of "exhaustive" from my point of view. > > > > > > > > > ii) .. and the different implementations are compile time > > > generated via C++ template classes > > > > I can't recall seeing any such samples, and according to the C++ style > > guide (see mozilla.org) that would not be portable. Could be done > > pretty simply though. > > I'm aware of the doc you mention. I completely agree with it when looking > from the full-blown Mozilla project view, even today - as opposed to some > discussion which took place on /. For my personal aims/project I probably > will relax this a little bit: > > allow "simple" C++ templates: > * no template template parameters > * no member templates > * possibly partial specialization > > But this whole point is really secondary. > > > > > > 2. If there are different ways of doing it, what questions should > > > I ask myself in choosing my way? > > > > Should you be using javascript or Python? Or using simple C++ > inheritance? > > I'm implementing components in C++ and using Python as a scripting > frontend. Consider using PyXPCOM :-) It works well. See below for an example :) > > > > > [snipped way more code than I have time to play with] > > You're right. I should have taken more time in stating my questions more > precise. > > > > > Mark. > > > > Thanks Mark, > > Toby. > Below is some gratuitous PyXPCOM hacking. It pulls a number of tricks - feel free to ask if you care about any of it :) It allows you to define all your functionality in a base class. This base class has access to your arbitary parameters. It creates 2 such objects, with contract IDs "@test.com/WorkHorse?foo=bar;spam=eggs" and "@test.com/WorkHorse?foo=green;spam=vikings" When you run regxpcom over this, it reports: - Registering: ParamClass: foo=bar;spam=eggs Registering: ParamClass: foo=green;spam=vikings - When you execute the test code (included in the same source), it reports: - Workhorse object created. My params are {'foo': 'bar', 'spam': 'eggs'} Workhorse object created. My params are {'foo': 'green', 'spam': 'vikings'} Created the objects OK! - The source code is below. Mark. # Parameterised contract IDs. import new # Our class with all the functionality. # self._params_ will hold our contract ID's params. class _Workhorse: _com_interfaces_ = "nsISupports" def __init__(self): print "Workhorse object created. My params are", self._params_ # Helper function that creates new class objects def MakeParameterisedClass( params, classid): dict = {} param_string = ";".join(["%s=%s" % i for i in params.items()]) dict['_reg_contractid_'] = "@test.com/WorkHorse?" + param_string dict['_reg_clsid_'] = classid dict['_params_'] = params name = "ParamClass: " + param_string klass = new.classobj(name, (_Workhorse,), dict) return klass # Create all the classes - specify the params, and a CLSID. class1 = MakeParameterisedClass( {"foo" : "bar", "spam" : "eggs"}, "{999a4477-e478-45ea-a789-35268625510a}") class2 = MakeParameterisedClass( {"foo" : "green", "spam" : "vikings"}, "{7a5921f3-a056-4092-b238-cb7fa50e324e}") # self-test code. if __name__=='__main__': from xpcom import components ob = components.classes["@test.com/WorkHorse?foo=bar;spam=eggs"].createInstance() ob = components.classes["@test.com/WorkHorse?foo=green;spam=vikings"].createInstance() print "Created the objects OK!"
