In this example, we're going to assume that I have an AirlineInfo COM component written with Microsoft Visual C++ and ATL. I won't go through all the steps needed to build this component right here because I want to concentrate on the .NET and C# angles. However, I'll explain the salient code and mention that the entire Visual C++ project is on the companion CD.
Our COM component is designed to produce the arrival details for a specific airline. For simplicity, let's say that the component returns details for the Air Scooby IC 5678 airline and will return an error for any other airline. I purposely inserted this error mechanism so that you can take a look at how the error raised by the COM component can be propagated back and be caught by the calling .NET client application.
Here's the IDL for the COM component: -
interface IAirlineInfo : IDispatch { [id(1), helpstring("method GetAirlineTiming")] HRESULT GetAirlineTiming([in] BSTR bstrAirline, [out,retval] BSTR* pBstrDetails); [propget, id(2), helpstring("property LocalTimeAtOrlando")] HRESULT LocalTimeAtOrlando([out, retval] BSTR *pVal); };
Nothing too exciting here, even to the most junior of COM developers. We have an interface named IAirlineInfo with two methods: GetAirlineTiming and LocalTimeAtOrlando. Now let's look at the actual implementation of the GetAirlineTiming method: -
STDMETHODIMP CAirlineInfo::GetAirlineTiming(BSTR bstrAirline, BSTR *pBstrDetails) { _bstr_t bstrQueryAirline(bstrAirline); if(NULL == pBstrDetails) return E_POINTER; if(_bstr_t("Air Scooby IC 5678") == bstrQueryAirline) { // Return the timing for this Airline. *pBstrDetails = _bstr_t(_T("16:45:00 - Will arrive at Terminal 3")).copy(); } else { // Return an error message. return Error(LPCTSTR(_T("Not available" )), __uuidof(AirlineInfo), AIRLINE_NOT_FOUND); } return S_OK; }
The GetAirlineTiming method takes two arguments. The first (bstrAirline) is a BSTR that represents the airline, and the second (pBstrDetails) is an output parameter that returns the arrival information (local time and gate). Within the method, we check that the value of the incoming bstrAirline parameter is equal to "Air Scooby IC 5678". If it is, we return some hard-coded arrival information. If the value is not what we're expecting, we call an error method to return the fact that we support only one airline.
With this basic overview of the component out of the way, let's take a look at generating metadata from the component's type library (typelib) so that the .NET client can use this metadata to talk to our component and invoke its methods.