使用 TypInfo 例程设置 属性 值
Set property value with TypInfo routine
通过以下方法将数据集字段值分配给属性:
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服务器: binary type) to it, 我该如何用这个方法做到这一点?
您可以使用 DataSet 的 CreateBlobStream()
方法为所需的 TField
获取只读 TStream
,用它做任何您需要的事情,然后在完成后释放它。
如果可能,您应该更改 属性 以接受任何一般性 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;
通过以下方法将数据集字段值分配给属性:
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服务器: binary type) to it, 我该如何用这个方法做到这一点?
您可以使用 DataSet 的 CreateBlobStream()
方法为所需的 TField
获取只读 TStream
,用它做任何您需要的事情,然后在完成后释放它。
如果可能,您应该更改 属性 以接受任何一般性 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;