3

我想在我正在编写的类中查询一些属性(又名注释)。

我可以用复杂的方式来做,但我想改用 Spring4D。

它有一个名为的单元Reflection,看起来它有我需要的东西,但我不知道如何使用它。

我在网上看过,但没有关于如何使用本机的示例。

我发现:

THasAttributeFilter 

看起来像这样:

  THasAttributeFilter<T: TRttiObject> = class(TMemberSpecificationBase<T>)
  private
    fAttributeClass: TAttributeClass;
  protected
    function Accept(const member: T): Boolean; override;
  public
    constructor Create(attributeClass: TAttributeClass);
  end;

太好了,所以我创建了一个像这样的过滤器:

type
  Capability = (CanDoA, CanDoB);
  TCapabilities = set of Capability;

[Capabilities(CanDoA)]
TMyClass = class(TParent)
strict private
  class var fCapabilities: TCapabilities;
....
public
  property Capabilities: TCapabilities read GetCapabilities;
end;

我可以像这样创建一个 HasAttributeFilter:

HasAttr:= THasAttributeFilter<TMyClass>.Create(CapabilitiesAttribute);
... ?? now what ??

我如何使用 Spring4D 来测试属性,而不必编写经典 RTTI 写作(例如根据 Nick Hodges 的书)所需的无数行?

4

1 回答 1

3

这些过滤器是使用规范模式实现的。另请参见 Spring.DesignPatterns.pas。

当您需要IEnumerable<T>.Where()方法中的委托时使用它们。

这是从 Spring4D 本身(Spring.Container.Builder)中截取的代码:

var
  condition: TPredicate<TRttiMethod>;
  method: TRttiMethod;
  ...
begin
  condition := TMethodFilters.IsInstanceMethod
    and TMethodFilters.HasAttribute(InjectAttribute)
    and not TMethodFilters.HasParameterFlags([pfOut, pfVar])
    and not TMethodFilters.IsConstructor;
  for method in model.ComponentType.Methods.Where(condition) do
    ...

可以看到,不同的规范可以结合布尔逻辑形成一个表达式:方法必须是实例方法并且必须具有InjectAttribute,不能有out或var参数,并且不能是构造函数。

然后可以将此组合规范分配给 a TPredicate<T>,然后将其传递给 Where 方法。

每个 TMethodFilters 返回的TSpecification<T>是一个带有运算符重载的记录,这使得布尔逻辑并将其分配给一个TPredicate<T>可能。

使用规范模式会产生非常可读和可组合的代码,因为您将所有内容分开。循环不会因为内部如何确定它是否是构造函数或方法具有哪些类型的参数而变得混乱,因为每个规范都封装在自己的类中。

PSMethodsTRttiTypeHelper来自 Spring.Helpers 的属性,它返回IEnumerable<TRttiMethod>.

于 2014-07-16T19:11:19.943 回答