一个运行时类最多可以有一个激活工厂。每次使用Activatable 宏之一都会为运行时类型注册一个激活工厂。因此,您的库中的以下代码
ActivatableClass(Math);
ActivatableStaticOnlyFactory(MathStatics);
尝试注册两个激活工厂:第一个为Math 类注册一个简单的激活工厂,第二个注册另一个实际上不可用的简单激活工厂(我们马上就会知道原因)。
因为第一个简单的激活工厂与Math 类相关联,所以当C# 组件尝试调用静态成员函数时它会被返回。然后,C# 组件尝试将此接口指针转换为 IMathStatics 接口,而简单激活工厂未实现该接口,因此转换失败,您将获得 InvalidCastException。
由于给定的运行时类只能有一个激活工厂,因此您的MathStatics 类需要同时实现IMathStatics 静态成员接口和IActivationFactory 接口,该接口用于默认构造(这是必需的因为您使用不带工厂接口名称的 activatable 属性将 Math 类型声明为默认可构造类型)。
您的激活工厂需要像这样实现:
class MathStatics : public ActivationFactory<IMathStatics>
{
InspectableClassStatic(RuntimeClass_WRLNativeComponent_Math, BaseTrust);
public:
MathStatics() {}
~MathStatics() {}
STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) override
{
return MakeAndInitialize<Math>(ppvObject);
}
STDMETHODIMP FastAdd(_In_ int a, _In_ int b, _Out_ int* value) override
{
if (value == nullptr) return E_POINTER;
*value = a + b;
return S_OK;
}
};
ActivatableClassWithFactory(Math, MathStatics);
ActivationFactory 基类模板提供了IActivationFactory 接口的默认实现。当客户端尝试默认构造 Math 类型的实例时,此默认实现仅返回 E_NOTIMPL,因此我们需要重写此成员函数以实际默认构造 Math 对象。
注意,当使用InspectableClassStatic为激活工厂完成IInspectable的实现时,类名应该是运行时类的名称(本例中为RuntimeClass_WRLNativeComponent_Math),而不是静态接口。激活是按类型名称执行的,WRL 基础结构使用此名称来查找使用其名称的运行时类型的激活工厂。
ActivatableClassWithFactory 用于向关联的激活工厂注册运行时类。