标签: rtti

Rtti 调用一个类方法说无效类型转换

我制作了一个非常通用的单元,其中的设置对象都是 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)

delphi casting rtti delphi-10.1-berlin

2
推荐指数
1
解决办法
852
查看次数

退出 RTTI 相关函数后发生访问冲突:结果消失

以前我有一个函数可以通过 RTTI 获取对象属性并设置它的值。现在我决定将其拆分为TRTTI.GetObjPropTRTTI.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 rtti

2
推荐指数
1
解决办法
309
查看次数

使用 RTTI 方法调用返回的函数引用

在 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)

delphi rtti delphi-10.2-tokyo

2
推荐指数
1
解决办法
410
查看次数

使用 RTTI 从 tkSet 类型获取可能值和当前值

可能有人已经问过这个问题,但还没有找到,所以问题来了:

我想解析组件的 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)

delphi rtti

2
推荐指数
1
解决办法
510
查看次数

如何获取方法链接泛型类型的 TRTTIType

我使用德尔福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)

delphi rtti delphi-10.3-rio

2
推荐指数
1
解决办法
262
查看次数

C++ std::any 将 std::any 的 C 字符数组转换为字符串的函数

#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)

c++ string c-strings rtti stdany

2
推荐指数
1
解决办法
962
查看次数

与Java的this.getClass()。getSimpleName();等效的C ++

在Java中,如果要使用对象类的名称,可以编写:

String myString = this.getClass().getSimpleName();
Run Code Online (Sandbox Code Playgroud)

C ++的等效功能是什么?也就是说,如何获取具有类名称的字符串*this

c++ java class names rtti

1
推荐指数
1
解决办法
1276
查看次数

在运行时将对象转换为其父对象

我通过了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作为父类,但它会导致问题,我后来阅读文档,发现它甚至不应该首先被调用.

delphi casting rtti

1
推荐指数
1
解决办法
190
查看次数

decltype导致is_same <T,T>失败(相同类型)

在下面的代码片段中,我可以使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)

c++ templates rtti decltype type-traits

1
推荐指数
1
解决办法
431
查看次数

为什么要宣布成员公开而不是发表?

宣布成员优先publishedpublic:

那么宣布成员public而不是published?请问published有什么缺点?或者我应该经常宣布成员published吗?


PS:不重复; 在发布我的问题之前,我已经阅读了这个问题及其所有答案."可能重复"的问题解释了两个关键字之间的区别,但在使用任何一个关键字时都没有提供指导,或者使用任何一个关键字的优点/缺点.

delphi rtti

1
推荐指数
1
解决办法
147
查看次数