我制作了一个非常通用的单元,其中的设置对象都是 TObject,我不想使用任何单元,这就是我这样做的原因。所以我的方法是使用RTTI来调用一切。但是现在我面临一个问题,我可以调用所有函数并提供参数和所有内容,但是当该方法是类过程/函数时,我无法调用它并且它说无效类型转换。
我查看了 embarcadero 的网站,它说当我们在 classmethod 上调用 rtti.invoke 时,我们必须将 Args 中的第一个参数设置为类引用。我试过了,但它不起作用。看看我的代码:
function TSomething.ExecMethodAndRet(MethodName: string;
Args: array of TValue): TObjectList<TObject>;
var
R : TRttiContext;
T : TRttiType;
M : TRttiMethod;
lArgs : array of TValue;
i : integer;
begin
T := R.GetType(MainObj.ClassInfo);
for M in t.GetMethods do
if (m.Parent = t) and (UpperCase(m.Name) = UpperCase(MethodName))then
begin
if (m.IsClassMethod) then
begin
for I := 0 to Length(Args) do
lArgs := [args[i]];
lArgs := [MainObj] + lArgs;
result := M.Invoke(MainObj, Args).AsType<TObjectList<TObject>>; <- this …Run Code Online (Sandbox Code Playgroud) 以前我有一个函数可以通过 RTTI 获取对象属性并设置它的值。现在我决定将其拆分为TRTTI.GetObjProp和TRTTI.SetObjPropValue,以便缓存返回的值TRTTI.GetObjProp并加快数据处理速度。
之后发生了奇怪的事情。首先,我突然注意到它ctx.GetType有效并且一直有效,尽管我从未初始化过该ctx变量。好吧,如果我用 初始化它TRttiContext.Create(),第二个奇怪的地方没有任何变化:
我调用该TRTTI.GetObjProp函数,只要我在该函数中,Result就已定义,并且我可以使用调试器请求它的属性。当我退出该函数时,我尝试请求rprop变量的相同属性并收到访问冲突错误。根据调试器,rprop已定义。
procedure TConfManager._setValue(indicator: TComponent; name: string; value: OleVariant);
var
rprop: TRttiProperty;
begin
rprop := TRTTI.GetObjProp(indicator, name);
//Access violation here when I try to use rprop
TRTTI.SetObjPropValue(indicator, rprop, value);
end;
class function TRTTI.GetObjProp(obj: TObject; propName: string): TRttiProperty;
var
ctx: TRttiContext;
rtyp: TRttiType;
begin
if obj = nil then Exit(nil);
rtyp := ctx.GetType(obj.ClassType);
Result := rtyp.GetProperty(propName);
end; …Run Code Online (Sandbox Code Playgroud) 在 Delphi 程序中,有以下模式:
TDelegate=reference to procedure(const Arg: TMyType);
TRouter = class
...
public
procedure RegisterHandler(const route: string: handler: TDelegate);
end;
THandlerContainer = class
public
function getDelegate: TDelegate;
procedure register(const Router: TRouter);
end; // class
...
procedure THandlerContainer.register(const router: TRouter)
begin
router.RegisterHandler('route', getDelegate);
end;
Run Code Online (Sandbox Code Playgroud)
基本上,我正在注册用于处理一些消息处理的函数引用(基于“route”字符串)。
我想为我的同事简化这个模式,这样他们就不必为每个实现调用 router.RegisterHandler 自己,而只需向他们的类添加一个属性,然后将一个实例传递给 TRouter 的方法,该方法将使用 RTTI找到所有由该属性修饰的方法并注册它们。
因此,我为该装饰创建了一个简单的属性RegisterMessageHandlerAttribute(使用自定义构造函数来接收路由字符串),并编写了一个 TRouter 方法,该方法使用 RTTI 来查找用该属性装饰的所有方法:
function TRouter.RegisterHandlers(const HandlerContainerClass:
TObject);
var
RTTIContext: TRttiContext;
RttiType : TRttiType;
prop: TRttiMethod;
Attr: TCustomAttribute;
begin
RTTIContext := TRttiContext.Create;
try
RttiType := RTTIContext.GetType(HandlerContainerClass);
if …Run Code Online (Sandbox Code Playgroud) 可能有人已经问过这个问题,但还没有找到,所以问题来了:
我想解析组件的 tkSet 属性(在我们的例子中为 Panel1),但我不知道如何正确执行此操作。我能够使用 rContext.FindType() 找到该集合的基本枚举类型,但我几乎确定有一些更优雅/简单的方法可以做到这一点。从那时起我就完全迷失了。我应该仔细检查该枚举类型的值,并根据组件的当前属性值检查每个值。
procedure TForm12.GetProperties2;
var
rContext: TRttiContext;
rType: TRttiType;
rProp: TRttiProperty;
begin
rType := rContext.GetType(Panel1.ClassType);
for rProp in rType.GetProperties do
begin
if (rProp.Visibility in [mvPublished]) and (rProp.PropertyType.TypeKind in [tkSet]) and (rProp.Name = 'Anchors') then
begin
Memo1.Lines.Add('Name: ' + rProp.Name);
Memo1.Lines.Add('PropertyType: ' + rProp.PropertyType.ToString);
Memo1.Lines.Add('Value: ' + rProp.GetValue(Panel1).ToString);
Memo1.Lines.Add('QualifiedName: ' + rProp.PropertyType.QualifiedName);
Memo1.Lines.Add('ElementType: ' + rContext.FindType(rProp.PropertyType.QualifiedName).AsSet.ElementType.ToString);
// here comes the desired results
Memo1.Lines.Add('Possible values:');
Memo1.Lines.Add(' 0 > akLeft');
Memo1.Lines.Add(' 1 > akTop');
Memo1.Lines.Add(' 2 > akRight'); …Run Code Online (Sandbox Code Playgroud) 我使用德尔福10.3。这是获取对应实例变量的一种例程TRTTIType。但是有什么方法可以填补此处标记为“缺少代码”的空白:
function getGenericTypeName<T> : string;
var
ctx : TRTTIContext;
aRT : TRTTIType;
begin
ctx := TRTTIContext.Create;
try
aRT := *** missing code for T *** // Get the TRTTIType for type T
result := aRT.Name;
finally
ctx.Free;
end;
end;
Run Code Online (Sandbox Code Playgroud) #include <iostream>
#include <any>
#include <string>
#include <vector>
#include <map>
using namespace std;
string AnyPrint(const std::any &value)
{
cout << size_t(&value) << ", " << value.type().name() << " ";
if (auto x = std::any_cast<int>(&value)) {
return "int(" + std::to_string(*x) + ")";
}
if (auto x = std::any_cast<float>(&value)) {
return "float(" + std::to_string(*x) + ")";
}
if (auto x = std::any_cast<double>(&value)) {
return "double(" + std::to_string(*x) + ")";
}
if (auto x = std::any_cast<string>(&value)) {
return "string(\"" + (*x) + "\")"; …Run Code Online (Sandbox Code Playgroud) 在Java中,如果要使用对象类的名称,可以编写:
String myString = this.getClass().getSimpleName();
Run Code Online (Sandbox Code Playgroud)
C ++的等效功能是什么?也就是说,如何获取具有类名称的字符串*this?
我通过了TObject.我知道这个对象来自TBaseClass.我想要做的是显示每个班级的所有已发布属性,直到TBaseClass.可能有更好的方法来做到这一点,但我正在尝试的是:
lObj := aObject;
while lObj.ClassType <> TBaseClass do
begin
lRttiType := lRttiContext.GetType(aObject.ClassType);
lProps := lRttiType.GetDeclaredProperties;
lStartIdx := Length(lAllProps);
SetLength(lAllProps, Length(lAllProps) + Length(lProps));
for I := Low(lProps) to High(lProps) do
lAllProps[lStartIdx + I] := lProps[I];
lObj := lObj as lObj.ClassParent;
// lObj := lObj.ClassParent.InitInstance(lObj); // *see below
end;
Run Code Online (Sandbox Code Playgroud)
这段代码的问题在于lObj.ClassType之后不会改变lObj as lObj.ClassParent.有人可以解释为什么这不起作用并提供一些有用的东西吗?
*这似乎有效,因为它将lObj.ClassType作为父类,但它会导致问题,我后来阅读文档,发现它甚至不应该首先被调用.
在下面的代码片段中,我可以使is_same声称两种类型是不同的,即使它们具有相同的受损名称,并且这在GCC和clang中都有效.这只发生在我使用decltype时,如果我使用注释掉的行,那么编译器认为两种类型都与预期相同.这是某种预期的标准符合行为,还是这个错误?
#include <iostream>
#include <type_traits>
#include <typeinfo>
template <typename T, typename X>
void show(T, X)
{
auto same = std::is_same<typename T::bar, X>::value;
std::cout << "They are " << (same ? "the same" : "NOT the same") << std::endl;
// the same string is always printed both times
std::cout << typeid(typename T::bar).name() << std::endl;
std::cout << typeid(X).name() << std::endl;
}
template <typename T>
struct Foo
{
static constexpr struct E {} nested {};
using bar = decltype(nested); // They are NOT …Run Code Online (Sandbox Code Playgroud) 宣布成员优先published于public:
那么宣布成员public而不是published?请问published有什么缺点?或者我应该经常宣布成员published吗?
PS:不重复; 在发布我的问题之前,我已经阅读了这个问题及其所有答案."可能重复"的问题解释了两个关键字之间的区别,但在使用任何一个关键字时都没有提供指导,或者使用任何一个关键字的优点/缺点.