You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Delphi 11 Pro中TAureliusDataset结合自定义Money数据类型的无效类类型转换异常解决求助

解决Delphi 11 + TMS Aurelius中自定义Money类型的TAureliusDataset类型转换异常

我碰到过类似的自定义值类型和Aurelius数据集配合的问题,你的核心问题在于Aurelius无法通过RTTI正确识别Money记录类型的转换规则,同时手动指定的TIntegerField和自定义类型的映射没有被框架正确处理。以下是几个经过验证的解决方案:

1. 修正Money类型的RTTI配置

你的BusOfc.Types.Money单元中的RTTI指令过于严格,导致Aurelius无法获取到Money类型的属性访问器和转换操作符的信息。修改单元顶部的RTTI指令:

替换原来的:

{$RTTI EXPLICIT FIELDS([vcPrivate])}

为:

{$RTTI EXPLICIT METHODS([vcPublic]) PROPERTIES([vcPublic]) FIELDS([vcPrivate])}

这个配置会暴露Money类型的所有公共方法和属性的RTTI信息,Aurelius需要这些信息来完成类型转换和属性赋值。同时保留单元开头的{$M+}指令,它是启用运行时类型信息的关键。

2. 注册Aurelius自定义类型转换器

Aurelius需要明确的规则来在MoneyInteger之间双向转换,你需要注册一个自定义类型转换器。

首先在Unit7中引用Aurelius.Types.Converters单元,然后添加转换器注册函数:

uses
  ..., Aurelius.Types.Converters;

procedure RegisterMoneyConverter;
begin
  TTypeConverter.RegisterConverter(
    TypeInfo(Money),
    TypeInfo(Integer),
    // 从Money转换到Integer
    function(const Value: TValue): TValue
    var
      LMoney: Money;
    begin
      LMoney := Value.AsRecord;
      Result := TValue.From<Integer>(LMoney.Value);
    end,
    // 从Integer转换到Money
    function(const Value: TValue): TValue
    var
      LMoney: Money;
    begin
      try
        LMoney.Value := Value.AsInteger;
        Result := TValue.From<Money>(LMoney);
      except
        on E: Exception do
          // 这里可以添加输入值的异常处理,比如提示用户输入合法金额
          raise Exception.Create('Invalid money value: ' + E.Message);
      end;
    end
  );
end;

然后在FormCreate方法中先注册转换器,再初始化数据集

procedure TForm7.FormCreate(Sender: TObject);
begin
  RegisterMoneyConverter;
  FList := TObjectList<TTest>.Create;
  AureliusDataset1.SetSourceList(FList, True);
  AureliusDataset1.Open;
end;

3. 调整TAureliusDataset的字段设置

如果你手动添加的TIntegerField和Money类型的映射冲突,可以尝试两种方式:

方式A:让Aurelius自动生成字段

删除你手动添加的AureliusDataset1Money字段,设置AureliusDataset1.AutoCreateFields := True,让框架根据实体类的属性自动生成适配的字段:

procedure TForm7.FormCreate(Sender: TObject);
begin
  RegisterMoneyConverter;
  FList := TObjectList<TTest>.Create;
  AureliusDataset1.AutoCreateFields := True; // 启用自动字段创建
  AureliusDataset1.SetSourceList(FList, True);
  AureliusDataset1.Open;
end;

方式B:使用TAureliusValueField替换TIntegerField

如果你想保留手动字段配置,把TIntegerField换成Aurelius专门为自定义值类型设计的TAureliusValueField,它能更好地处理RTTI驱动的类型转换。

额外提示

  • 你的Money类型的SetValue方法会在值为0或负数时抛出异常,记得在数据集提交时添加异常捕获逻辑,避免程序崩溃。
  • 测试时先输入合法的正整数值(比如100)验证功能正常,再测试边界情况。

内容的提问来源于stack exchange,提问作者Terry Thompson

火山引擎 最新活动