Can I pass a Class type as a procedure parameter

﹥>﹥吖頭↗ 提交于 2019-12-12 09:46:25

问题


I want to create a function that returns all the names of a certain class as a string list. Based on the previous solution / question I tried to this code with no success

function  GetClassElementNames (TObject ) : TStringlist ;
var
  LCtx : TRttiContext;
  LMethod : TRttiMethod;
begin
  try
    LCtx:=TRttiContext.Create;
    try
      // list the methods for the any class  class
      for LMethod in  LCtx.GetType(TObject).GetMethods do
        result.add(LMethod.Name);
    finally
      LCtx.Free;
    end;
  except
    on E: Exception do
      result.add (E.ClassName + ': ' +  E.Message);
  end;
end;

回答1:


Use TClass for that, which TRttiContent.GetType() expects anyway.

You are also not allocating the Result before filling it.

Try this:

function GetClassElementNames(Cls: TClass) : TStringlist ;
var
  LCtx : TRttiContext;
  LMethod : TRttiMethod;
begin
  Result := TStringList.Create;
  try
    LCtx := TRttiContext.Create;
    try
      for LMethod in LCtx.GetType(Cls).GetMethods do
        Result.Add(LMethod.Name);
    finally
      LCtx.Free;
    end;
  except
    on E: Exception do
      Result.Add(E.ClassName + ': ' +  E.Message);
  end;
end;

var
  Methods: TStringList;
begin
  Methods := GetClassElementNames(TSomeClass);
  try
    ...
  finally
    Methods.Free;
  end;
end;

If you want to pass in an object instance instead of a class type, you can wrap GetClassElementNames() like this:

function GetObjectElementNames(Object: TObject): TStringList;
begin
  Result := GetClassElementNames(Object.ClassType);
end;

With that said, it is not a good idea to return a new TStringList object. It is better, and more flexible, if the caller allocates the TStringList and passes it to the function to fill in, eg:

procedure GetClassElementNames(Cls: TClass; AMethods: TStrings);
var
  LCtx : TRttiContext;
  LMethod : TRttiMethod;
begin
  try
    LCtx := TRttiContext.Create;
    try
      for LMethod in LCtx.GetType(Cls).GetMethods do
        AMethods.Add(LMethod.Name);
    finally
      LCtx.Free;
    end;
  except
    on E: Exception do
      AMethods.Add(E.ClassName + ': ' +  E.Message);
  end;
end;

{
procedure GetObjectElementNames(Object: TObject; AMethods: TStrings);
begin
  GetClassElementNames(Object.ClassType, AMethods);
end;
}

var
  Methods: TStringList;
begin
  Methods := TStringList.Create;
  try
    GetClassElementNames(TSomeClass, Methods);
    ...
  finally
    Methods.Free;
  end;
end;


来源:https://stackoverflow.com/questions/19063916/can-i-pass-a-class-type-as-a-procedure-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!