如何将返回非Windows运行时类型的受保护方法添加到C++/WinRT基类



我得到了以下C++/CX代码,它按预期工作,但希望将其转换为C++/WinRT代码:

namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class BaseClass : public Windows::UI::Xaml::Controls::SwapChainPanel
{
public:
BaseClass();
void PublicMethod();
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}

namespace My.Custom.Stuff
{
[Windows::Foundation::Metadata::WebHostHidden]
public ref class SubClass sealed : public BaseClass
{
public:
SubClass();
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod()
// ...
}
};
}

然而,我遇到的问题如下:BaseClass包含一个受保护的方法,该方法返回的类型无法映射到相应的Windows运行时类型。在C++/CX中,这不是问题,因为ProtectedMethod根本没有映射。如果我使用我的Windows运行时组件ProtectedMethod,那就是我想要的。

但是,该方法应该是BaseClass的成员,因为像SubClass这样的多个其他类在实现其公共方法时使用该方法。我已经想出了以下C++/WinRT MIDL代码:

namespace My.Custom.Stuff
{
unsealed runtimeclass BaseClass : Windows.UI.Xaml.Controls.SwapChainPanel
{
BaseClass();
void PublicMethod();
// This does not work
protected DirectX.XMFLOAT3 RgbFromBrush(IInspectable brush);
}
}

import "BaseClass.idl";

namespace My.Custom.Stuff
{
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}

问题是,如果我以这种方式定义ProtectedMethod,它将不起作用,因为::DirectX::XMFLOAT3不是Windows运行时类型。如果我使用任何其他返回类型,受保护的方法就会被映射。但是,当使用Windows运行时组件时,它不应该是可见的,当然我不应该更改它的返回类型。

如何使用C++/WinRT实现我对C++/CX的操作?

编辑

编译MIDL代码的结果如下:

#include "BaseClass.g.h"

namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
// ...
};
}

namespace winrt::My::Custom::Stuff::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}

我认为可以简单地添加受保护的方法如下:

namespace winrt::My::Custom::Stuff::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
protected:
static ::DirectX::XMFLOAT3 ProtectedMethod();
};
}

但是,尝试在SubClass中使用ProtectedMethod会导致以下错误:

error C2039: 'ProtectedMethod': is not a member of 'winrt::My::Custom::Stuff::BaseClass'

以下是我如何使用它:

#include "SubClass.g.h"

namespace winrt::My::Custom::Stuff::implementation
{
struct SubClass : SubClassT<SubClass>
{
SubClass() = default;
void UseProtectedMethod()
{
::DirectX::XMFLOAT3 value = ProtectedMethod();
}
};
}

namespace winrt::My::Custom::Stuff::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}

从C++/CX转换到C++/WinRT时,只有公共方法才能进入IDL文件,因为这些方法是构成WinRT API曲面的唯一方法。

私有/受保护/内部的方法不是WinRT API表面的一部分,因此它们不应进入IDL。

您发布的使用代码不应该编译,因为implementation::SubClass的C++定义缺少一个模板参数。由于IDL/WinRT定义具有从BaseClass派生的SubClass,因此需要将BaseClass的实现类型提供给SubClassT,并且如果检查cppwirt生成的";h"子类;,你会看到这种情况发生的。一旦您正确地声明了SubClass的实现,您就可以访问BaseClass上受保护的方法。

我刚刚成功地尝试了一下,它看起来像这样:

BaseClass.idl

namespace RuntimeComponent1
{
[default_interface]
unsealed runtimeclass BaseClass
{
BaseClass();
void PublicMethod();
}
}

基本类.h

#pragma once
#include "BaseClass.g.h"
struct non_winrt_type
{
};
namespace winrt::RuntimeComponent1::implementation
{
struct BaseClass : BaseClassT<BaseClass>
{
BaseClass() = default;
void PublicMethod() {}
protected:
non_winrt_type ProtectedMethod()
{
return {};
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct BaseClass : BaseClassT<BaseClass, implementation::BaseClass>
{
};
}

子类.idl

import "BaseClass.idl";
namespace RuntimeComponent1
{
[default_interface]
runtimeclass SubClass : BaseClass
{
SubClass();
void UseProtectedMethod();
}
}

子类.h

#pragma once
#include "SubClass.g.h"
#include "BaseClass.h"
namespace winrt::RuntimeComponent1::implementation
{
// Notice how BaseClass is used here.
// This was copied directly from the generated boilerplate SubClass.h
struct SubClass : SubClassT<SubClass, RuntimeComponent1::implementation::BaseClass>
{
SubClass() = default;
void UseProtectedMethod()
{
auto result = ProtectedMethod();
}
};
}
namespace winrt::RuntimeComponent1::factory_implementation
{
struct SubClass : SubClassT<SubClass, implementation::SubClass>
{
};
}

最新更新