Hosting Manager Discovery


The COM interfaces in the hosting API are factored into a set of pluggable managers, as described earlier. This factoring allows a host to implement only the managers of interest in a particular scenario. The fact that a host can optionally provide a particular manager means the hosting interfaces must include a protocol by which the CLR can determine which, if any, managers a host chooses to implement. Remember, too, that some managers are implemented completely on the CLR side, such as the host protection manager used to enforce host-specific programming model considerations. These managers are always provided by the CLR if a host asks for them. As such, there must also be a mechanism for a host to ask for a particular CLRimplemented manager.

The discovery of the managers supported by a host and the managers supplied by the CLR are arbitrated through two interfaces named IHostControl and ICLRControl. As their names suggest, IHostControl is implemented by the host and ICLRControl is implemented by the CLR.

IHostControl contains a method called GetHostManager that the CLR uses to determine which managers a host supports, whereas ICLRControl contains a method called GetCLRManager that the host calls to obtain an interface pointer to one of the CLR managers.

Figure 2-3 shows the relationship between the host, the CLR, the control interfaces, and the hosting managers. For those managers in which the implementation is split between the CLR and the host, the primary manager interface is always provided by the host.

Figure 2-3. IHostControl, ICLRControl, and the hosting managers


Discovering Host-Implemented Managers

Now that we've looked at all the pieces, let's take a look at how the CLR determines which managers a host implements.

Step 1: The Host Supplies a Host Control Class

After the host's call to CorBindToRuntimeEx returns, the host initializes an instance of its host control class (that is, a class derived from IHostControl) and informs the CLR of its existence by calling ICLRRuntimeHost::SetHostControl. It's important to note that the host must do this before ICLRRuntimeHost::Start is calledcalls to SetHostControl that occur after Start have no effect.

Given a host-implemented control class such as the following:

class CHostControl : public IHostControl { public:    // Methods from IHostControl    HRESULT __stdcall GetHostManager(REFIID riid,                            void **ppObject);    // Additional methods, including those from IUnknown, omitted for clarity };

the code in the host to set the host control object looks like this:

ICLRRuntimeHost *pCLR = NULL; // Initialize the clr HRESULT hr = CorBindToRuntimeEx(L"v2.0.40103",                                 L"wks",                                 STARTUP_CONCURRENT_GC,                                 CLSID_CLRRuntimeHost,                                 IID_ICLRRuntimeHost,                                (PVOID*) &pCLR); // Initialize a new instance of our host control object CHostControl *pHostControl = new CHostControl(); // Tell the CLR about it... pCLR->SetHostControl((IHostControl *)pHostControl);

Step 2: The CLR Queries the Host Control Class

After CorBindToRuntimeEx returns, the CLR begins the process of setting itself up to run managed code. As part of this initialization, the CLR checks to see whether a host control has been registered (that is, the host called ICLRRuntimeHost::SetHostControl). If not, the host does not implement any managers as far as the CLR is concerned, and initialization proceeds. If a host control class has been registered, the CLR will call IHostControl::GetHostManager once for every manager for which the primary interface is implemented by the host. Specifically, GetHostManager will be called once for the following IIDs:

  • IID_IHostMemoryManager

  • IID_IHostTaskManager

  • IID_IHostThreadPoolManager

  • IIE_IHostIoCompletionManager

  • IID_IHostSyncManager

  • IID_IHostAssemblyManager

  • IID_IHostGCManager

  • IID_IHostPolicyManager

If a valid interface pointer is returned for a given IID, the host is said to implement that manager. If E_NOINTERFACE is returned, the host does not implement that manager.

Here's a sample host's implementation of IHostControl::GetHostManager that supports just the memory manager and the assembly loading manager:

HRESULT __stdcall CHostControl::GetHostManager(REFIID riid, void **ppObject) {    if (riid == IID_IHostMemoryManager)    {       // The CLR is asking for a memory manager. Create an instance of the       // host's memory manager and return it. Note: This snippet assumes       // the host's implementation of the memory manager is in       // a class named CHostMemoryManager       CHostMemoryManager *pMemManager = new CHostMemoryManager();          *ppObject = (IHostMemoryManager *)pMemManager;           return S_OK;    }    else if (riid == IID_IHostAssemblyManager)    {          // The CLR is asking for an assembly loading manager.  Create an          // instance of the host's manager and return it. Note: This          // snippet assumes the host's implementation of the Assembly Loading          // Manager is in a class named CHostAssemblyManager          CHostAssemblyManager *pAsmManager = new CHostAssemblyManager();          *ppObject = (IHostAssemblyManager *)pAssemblyManager;          return S_OK;    }    // This host doesn't support any other managers  so just return    // E_NOINTERFACE    *ppObject = NULL;    return E_NOINTERFACE; }

After the series of calls to GetHostManager, the CLR has a complete picture of which managers the host supports. From this point on, the CLR's interaction with the managers goes directly through each manager's primary interface. The host control object's only job is to return managers to the CLR. After that, it's out of the picture.

Obtaining CLR-Implemented Managers

As described earlier, the CLR provides a set of managers that hosts can use to customize various aspects of a running CLR. These managers are implemented completely on the CLR side. A host's interaction with these managers is very simple because the communication is all one wayfrom the host to the CLR.

The process a host uses to obtain interface pointers to the CLR-implemented managers is relatively straightforward. First, the host obtains an interface pointer to an ICLRControl by calling ICLRRuntimeHost::GetCLRControl. Next, the host calls ICLRControl::GetCLRManager, passing in the IID of the interface corresponding to the manager of interest. For example, the following code obtains a pointer to the failure policy manager, which is used to customize the way the CLR behaves in the face of resource failures:

// Get a pointer to an ICLRControl (pCLR is of type ICLRRuntimeHost *) ICLRControl *pCLRControl = NULL; pCLR->GetCLRControl(&pCLRControl); // Ask for the Failure Policy Manager ICLRPolicyManager *pPolicy = NULL; pCLRControl->GetCLRManager(IID_ICLRPolicyManager, (void **)&pPolicy);

Once the desired interface pointer is returned, the host saves it and calls the methods relevant to the customization it desires. The semantics of when each of the managers can be called and which settings can be configured varies by manager. The rest of this chapter provides an overview of each of the major hosting managers. Details about how to use these managers are provided in subsequent chapters in this book.



    Customizing the Microsoft  .NET Framework Common Language Runtime
    Customizing the Microsoft .NET Framework Common Language Runtime
    ISBN: 735619883
    EAN: N/A
    Year: 2005
    Pages: 119

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net