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