最后,在模块上调用GetClassObject方法,此方法你必须在组件代码实现,将返回一对CID / IID nsIFactory对象。
经常,你不需要先创建对象因为工厂的隐式地知道所支持IID。当并非这种情况,然而这样做进一步从具体类的抽象工厂,如果你有一个工厂
#define MOZILLA_STRICT_API
#include "nsIModule.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
static const nsIID kIModuleIID = NS_IMODULE_IID;
static const nsIID kIFactoryIID = NS_IFACTORY_IID;
static const nsIID kISupportsIID = NS_ISUPPORTS_IID;
static const nsIID kIComponentRegistrarIID = NS_ICOMPONENTREGISTRAR_IID;
#define SAMPLE_CID \
{ 0x777f7150, 0x4a2b, 0x4301, \
{ 0xad, 0x10, 0x5e, 0xab, 0x25, 0xb3, 0x22, 0xaa}}
static const nsCID kSampleCID = SAMPLE_CID;
class Sample: public nsISupports {
private:
nsrefcnt mRefCnt;
public:
Sample();
virtual ~Sample();
NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
};
Sample::Sample()
{
:mRefCnt(0);
}
Sample::~Sample()
{
}
NS_IMETHODIMP Sample::QueryInterface(const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
if (aIID.Equals(kISupportsIID)) {
*aResult = (void *) this;
}
if (aResult != NULL) {
return NS_ERROR_NO_INTERFACE;
}
AddRef();
return NS_OK ;
}
NS_IMETHODIMP_(nsrefcnt) Sample::AddRef()
{
return ++mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) Sample::Release()
{
if (--mRefCnt == 0) {
delete this;
return 0;
}
return mRefCnt;
}
// factory implementation class for component
class SampleFactory: public nsIFactory{
private:
nsrefcnt mRefCnt;
public:
SampleFactory();
virtual ~SampleFactory();
NS_IMETHOD QueryInterface(const nsIID &aIID, void **aResult);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID & iid, void * *result);
NS_IMETHOD LockFactory(PRBool lock);
};
SampleFactory::SampleFactory()
{
mRefCnt = 0;
}
SampleFactory::~SampleFactory()
{
}
NS_IMETHODIMP SampleFactory::QueryInterface(const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
if (aIID.Equals(kISupportsIID)) {
*aResult = (void *) this;
}
else
if (aIID.Equals(kIFactoryIID)) {
*aResult = (void *) this;
}
if (aResult != NULL) {
return NS_ERROR_NO_INTERFACE;
}
AddRef();
return NS_OK ;
}
NS_IMETHODIMP_(nsrefcnt) SampleFactory::AddRef()
{
return ++mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt) SampleFactory::Release()
{
if (--mRefCnt == 0) {
delete this;
return 0;
}
return mRefCnt;
}
NS_IMETHODIMP
SampleFactory::CreateInstance(nsISupports *aOuter, const nsIID & iid, void * *result)
{
if (!result)
return NS_ERROR_INVALID_ARG;
Sample* sample = new Sample();
if (!sample)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = sample->QueryInterface(iid, result);
if (NS_FAILED(rv)) {
*result = nsnull;
delete sample;
}
return rv;
}
NS_IMETHODIMP
SampleFactory::LockFactory(PRBool lock)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// Module implementation
class SampleModule : public nsIModule
{
public:
SampleModule();
virtual ~SampleModule();
// nsISupports methods:
NS_IMETHOD QueryInterface(const nsIID & uuid, void * *result);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// nsIModule methods:
NS_IMETHOD GetClassObject(nsIComponentManager *aCompMgr, const nsCID & aClass, const nsIID & aIID,
void * *aResult);
NS_IMETHOD RegisterSelf(nsIComponentManager *aCompMgr, nsIFile *aLocation, const char *aLoaderStr,
const char *aType);
NS_IMETHOD UnregisterSelf(nsIComponentManager *aCompMgr, nsIFile *aLocation, const char *aLoaderStr);
NS_IMETHOD CanUnload(nsIComponentManager *aCompMgr, PRBool *_retval);
private:
nsrefcnt mRefCnt;
};
//----------------------------------------------------------------------
SampleModule::SampleModule()
{
mRefCnt = 0;
}
SampleModule::~SampleModule()
{
}
// nsISupports implemention
NS_IMETHODIMP_(nsrefcnt)
SampleModule::AddRef(void)
{
++mRefCnt;
return mRefCnt;
}
NS_IMETHODIMP_(nsrefcnt)
SampleModule::Release(void)
{
--mRefCnt;
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
}
return mRefCnt;
}
NS_IMETHODIMP
SampleModule::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if ( !aInstancePtr )
return NS_ERROR_NULL_POINTER;
nsISupports* foundInterface;
if ( aIID.Equals(kIModuleIID) )
foundInterface = (nsIModule*) this;
else if ( aIID.Equals(kISupportsIID) )
foundInterface = (nsISupports*) this;
else
foundInterface = 0;
if (foundInterface) {
foundInterface->AddRef();
*aInstancePtr = foundInterface;
return NS_OK ;
}
*aInstancePtr = foundInterface;
return NS_NOINTERFACE;
}
// Create a factory object for creating instances of aClass.
NS_IMETHODIMP
SampleModule::GetClassObject(nsIComponentManager *aCompMgr,
const nsCID& aClass,
const nsIID& aIID,
void** result)
{
if (!kSampleCID.Equals(aClass))
return NS_ERROR_FACTORY_NOT_REGISTERED;
if (!result)
return NS_ERROR_INVALID_ARG;
SampleFactory* factory = new SampleFactory();
if (!factory)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = factory->QueryInterface(aIID, result);
if (NS_FAILED(rv)) {
*result = nsnull;
delete factory;
}
return rv;
}
//----------------------------------------
NS_IMETHODIMP
SampleModule::RegisterSelf(nsIComponentManager *aCompMgr,
nsIFile* aPath,
const char* registryLocation,
const char* componentType)
{
nsIComponentRegistrar* compReg = nsnull;
nsresult rv = aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
if (NS_FAILED(rv))
return rv;
rv = compReg->RegisterFactoryLocation(kSampleCID,
"Sample Class",
nsnull,
aPath,
registryLocation,
componentType);
compReg->Release();
return rv;
}
NS_IMETHODIMP
SampleModule::UnregisterSelf(nsIComponentManager* aCompMgr,
nsIFile* aPath,
const char* registryLocation)
{
nsIComponentRegistrar* compReg = nsnull;
nsresult rv = aCompMgr->QueryInterface(kIComponentRegistrarIID, (void**)&compReg);
if (NS_FAILED(rv))
return rv;
rv = compReg->UnregisterFactoryLocation(kSampleCID, aPath);
compReg->Release();
return rv;
}
NS_IMETHODIMP
SampleModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
{
*okToUnload = PR_FALSE; // we do not know how to unload.
return NS_OK ;
}
//----------------------------------------------------------------------
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
nsIFile* location,
nsIModule** return_cobj)
{
nsresult rv = NS_OK ;
// Create and initialize the module instance
SampleModule *m = new SampleModule();
if (!m) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Increase refcnt and store away nsIModule interface to m in return_cobj
rv = m->QueryInterface(kIModuleIID, (void**)return_cobj);
if (NS_FAILED(rv)) {
delete m;
}
return rv;
}