fdo#46808 - [Easy Hack] Adapt UNO services to new-style

Stephan Bergmann sbergman at redhat.com
Thu Mar 22 06:19:50 PDT 2012


On 03/22/2012 01:56 PM, Noel Grandin wrote:
> How do I decide whether to change the constructor to take
> XComponentContext or XMultiComponentFactory?

It is always XComponentContext that you want to move around, never 
XMultiComponentFactory.

In the old days, there was just XMultiServiceFactory, used for two 
different things:

* A global XMultiServiceFactory (passed around), through which client 
code can instantiate services it wants to use.

* Each service implementation itself has some XMultiServiceFactory (or 
XSingleServiceFactory; often hidden within the implementations behind 
some helper foo), through which the global XMultiServiceFactory obtains 
instances of the given service.  When the global XMultiServiceFactory 
instantiats a service, it passes a ref to itself to that service, so 
that that service in turn has a global XMultiServiceFactory where /it/ 
can instantiate further services from, if necessary.

With the introduction of the component context, things changed slightly:

* There is now a global XComponentContext.  It contains an 
XMultiComponentFactory (XComponentContext.getServiceManager) through 
which client code can instantiate services it wants to use.  (And 
new-style service constructors hide this 
getServiceManager()->createInstance(...) stuff.)

* An XMultiComponentFactory is like an XMultiServiceFactory, except it 
allows to pass on the (global) XComponentContext.  (And the 
implementation of the global XMultiComponentFactory also still supports 
the XMultiServiceFactory interface, for backwards compatibility.)

* Service implementations nowadays should have an XMultiComponentFactory 
(or XSingleComponentFactory) through which the global 
XComponentContext/XMultiComponentFactory can create instances of them 
(as that way those instances receive the global XComponentContext for 
internal use).  Again, there is helper foo to do just that 
(cppu::component_getFactoryHelper; see configmgr/source/services.cxx for 
a clean example of how such a factory for various services and 
singletons implemented within one library should look like).  For 
historic reasons, lots of service implementations still use the old way, 
though.

>> As a quick fix, you can pass comphelper::getProcessComponentContext()
>> (#include "comphelper/processfactory.hxx") into create(), but you
>> unfortunately cannot even commit that, as it violates module
>> dependencies (comphelper depends on ucbhelper, so ucbhelper cannot
>> depend on comphelper). The right fix is to change the
>> ResultSetImplHelper constructor and adapt all its uses accordingly.

For code not below comphelper that only has a global 
XMultiServiceFactory at hand, but rather needs an XComponentContext 
(e.g., to pass it into a new-style service constructor), 
comphelper::getComponentContext (comphelper/processfactory.hxx) can be 
used to convert the former into the latter.  (But the best fix, of 
course, is to change all places that currently have a reference to the 
global XMultiServiceFactory, to instead have a reference to the global 
XComponentContext.)

Stephan


More information about the LibreOffice mailing list