通过直接实例化组件,可以在不需要类工厂或其他机制时降低开销。 可以直接在通用 Windows 平台应用和桌面应用中实例化组件。
本文档演示了两个示例。 第一个示例使用 Make 函数实例化组件。 第二个示例使用 MakeAndInitialize 函数实例化可能在构造过程中失败的组件。 由于 COM 通常使用 HRESULT 值(而不是异常)来指示错误,因此 COM 类型通常不会从其构造函数引发。MakeAndInitialize 使组件能够通过 RuntimeClassInitialize 方法验证其构造自变量。这两个示例通过定义将消息写入控制台的类来定义基本记录器接口并实现该接口。
不能使用 new 运算符实例化 Windows 运行时 C++ 模板库组件。 因此,建议始终使用 Make 或 MakeAndInitialize 直接实例化组件。
创建和实例化基本记录器组件
1. 在 Visual Studio 中,创建 Win32 控制台应用程序项目。 为该项目命名,例如 WRLLogger。
2. 将 Midl 文件 (.idl) 添加到项目,将该文件命名为 ILogger.idl,然后添加以下代码:
import "ocidl.idl";
// Prints text to the console.
[uuid(AFDB9683-F18A-4B85-90D1-B6158DAFA46C)]
interface ILogger : IUnknown
{
HRESULT Log([in] LPCWSTR text);
}
3. 使用下面的代码替换 WRLLogger.cpp
的内容。
#include "pch.h" // Use stdafx.h in Visual Studio 2017 and earlier
#include <wrl\implements.h>
#include <comutil.h>
#include "ILogger_h.h"
using namespace Microsoft::WRL;
// Writes logging messages to the console.
class CConsoleWriter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, ILogger>
{
public:
STDMETHODIMP Log(_In_ PCWSTR text)
{
wprintf_s(L"%s\n", text);
return S_OK;
}
private:
// Make destroyable only through Release.
~CConsoleWriter()
{
}
};
int wmain()
{
ComPtr<CConsoleWriter> writer = Make<CConsoleWriter>();
HRESULT hr = writer->Log(L"Logger ready.");
return hr;
}
/* Output:
Logger ready.
*/
处理基本记录器组件的构造失败
使用以下代码替换 CConsoleWriter 类的定义。 此版本具有一个私有字符串成员变量并重写 RuntimeClass::RuntimeClassInitialize 方法。 如果调用 SHStrDup 失败,则 RuntimeClassInitialize 失败。
// Writes logging messages to the console.
class CConsoleWriter : public RuntimeClass<RuntimeClassFlags<ClassicCom>, ILogger>
{
public:
// Initializes the CConsoleWriter object.
// Failure here causes your object to fail construction with the HRESULT you choose.
HRESULT RuntimeClassInitialize(_In_ PCWSTR category)
{
return SHStrDup(category, &m_category);
}
STDMETHODIMP Log(_In_ PCWSTR text)
{
wprintf_s(L"%s: %s\n", m_category, text);
return S_OK;
}
private:
PWSTR m_category;
// Make destroyable only through Release.
~CConsoleWriter()
{
CoTaskMemFree(m_category);
}
};
使用下面的代码替换 wmain
的定义。 此版本使用 MakeAndInitialize
实例化 CConsoleWriter
对象并检查 HRESULT 结果。
int wmain()
{
ComPtr<CConsoleWriter> writer;
HRESULT hr = MakeAndInitialize<CConsoleWriter>(&writer, L"INFO");
if (FAILED(hr))
{
wprintf_s(L"Object creation failed. Result = 0x%x", hr);
return hr;
}
hr = writer->Log(L"Logger ready.");
return hr;
}
/* Output:
INFO: Logger ready.
*/