使用TypInfo例程设置属性值

时间:2015-03-18 18:15:59

标签: delphi delphi-xe delphi-xe6

将数据集字段值分配给由以下方法执行的属性:

var
  lvRuntimeContext: TRttiContext;
  lvRuntimeType: TRttiType;
  lvProp: TRttiProperty;
  lvAttr: TCustomAttribute;
  lvCol: EntityColumnAttrib;
begin

  if DataAccess.DataSet.Active then
  begin
    lvRuntimeContext := TRttiContext.Create;

    try
      lvRuntimeType := lvRuntimeContext.GetType(EntityColumnClassType);

      for lvProp in lvRuntimeType.GetProperties do
        for lvAttr in lvProp.GetAttributes do
          if lvAttr is EntityColumnAttrib then
          begin
            lvCol := (lvAttr as EntityColumnAttrib);

            if lvCol.InCurrentTable then
              case lvCol.FieldType of
                ftBytes: begin

                end;

                ftDateTime: lvProp.SetValue(ASystemColumns, TValue.From<TDateTime>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsDateTime));
              else
                lvProp.SetValue(ASystemColumns, TValue.From<Variant>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsVariant));
              end;

          end;
    finally
      lvRuntimeContext.Free;
    end;
  end;

在我的一个类中有一个类型为 TMemoryStream 的属性,我想从DataSet字段(SQL Server:二进制类型)赋值给它,怎么能我用这种方法做到了吗?

1 个答案:

答案 0 :(得分:3)

您可以使用DataSet的CreateBlobStream()方法获取所需TStream的只读TField,随身携带所需内容,然后在完成后将其释放。

如果可能,您应该将您的媒体资源更改为接受任何常规TStream,而不仅仅是TMemoryStream。这样,您可以通过RTTI直接将blob TStream分配给您的属性(TValue可以从任何TObject指针隐式创建):

var
  lvRuntimeContext: TRttiContext;
  lvRuntimeType: TRttiType;
  lvProp: TRttiProperty;
  lvAttr: TCustomAttribute;
  lvCol: EntityColumnAttrib;
  lStrm: TStream;
begin    
  if DataAccess.DataSet.Active then
  begin
    lvRuntimeContext := TRttiContext.Create;
    try
      lvRuntimeType := lvRuntimeContext.GetType(EntityColumnClassType);

      for lvProp in lvRuntimeType.GetProperties do
      begin
        for lvAttr in lvProp.GetAttributes do
        begin
          if lvAttr is EntityColumnAttrib then
          begin
            lvCol := (lvAttr as EntityColumnAttrib);

            if lvCol.InCurrentTable then
            begin
              case lvCol.FieldType of
                ftBytes: begin
                  lStrm := DataAccess.DataSet.CreateBlobStream(DataAccess.DataSet.FieldByName(lvCol.FieldName), bmRead);
                  try
                    lvProp.SetValue(ASystemColumns, lStrm);
                  finally
                    lStrm.Free;
                  end;
                end;

                ftDateTime: begin
                  lvProp.SetValue(ASystemColumns, TValue.From<TDateTime>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsDateTime));
                end;
              else
                lvProp.SetValue(ASystemColumns, TValue.From<Variant>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsVariant));
              end;
            end;
          end;
        end;
      end;
    finally
      lvRuntimeContext.Free;
    end;
  end;
end;

如果属性必须仅继续使用TMemoryStream,则必须创建临时TMemoryStream对象,将blob数据复制到其中(可以使用TStream.CopyFrom()),然后将其分配给属性:

var
  lvRuntimeContext: TRttiContext;
  lvRuntimeType: TRttiType;
  lvProp: TRttiProperty;
  lvAttr: TCustomAttribute;
  lvCol: EntityColumnAttrib;
  lBlobStrm: TStream;
  lMemStrm: TMemoryStream;
begin    
  if DataAccess.DataSet.Active then
  begin
    lvRuntimeContext := TRttiContext.Create;
    try
      lvRuntimeType := lvRuntimeContext.GetType(EntityColumnClassType);

      for lvProp in lvRuntimeType.GetProperties do
      begin
        for lvAttr in lvProp.GetAttributes do
        begin
          if lvAttr is EntityColumnAttrib then
          begin
            lvCol := (lvAttr as EntityColumnAttrib);

            if lvCol.InCurrentTable then
            begin
              case lvCol.FieldType of
                ftBytes: begin
                  lMemStrm := TMemoryStream.Create;
                  try
                    lBlobStrm := DataAccess.DataSet.CreateBlobStream(DataAccess.DataSet.FieldByName(lvCol.FieldName), bmRead);
                    try
                      lMemStrm.CopyFrom(lBlobStrm, 0);
                    finally
                      lBlobStrm.Free;
                    end;
                    lMemStrm.Position := 0;
                    lvProp.SetValue(ASystemColumns, lMemStrm);
                  finally
                    lMemStrm.Free;
                  end;
                end;

                ftDateTime: begin
                  lvProp.SetValue(ASystemColumns, TValue.From<TDateTime>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsDateTime));
                end;
              else
                lvProp.SetValue(ASystemColumns, TValue.From<Variant>(DataAccess.DataSet.FieldByName(lvCol.FieldName).AsVariant));
              end;
            end;
          end;
        end;
      end;
    finally
      lvRuntimeContext.Free;
    end;
  end;
end;