如何在Spring4d中使用THasAttributeFilter

时间:2014-07-16 15:09:55

标签: delphi attributes spring4d

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

我可以用复杂的方式来做,但我想改用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的书)?

1 个答案:

答案 0 :(得分:3)

这些过滤器是使用Specification Pattern实现的。 另请参见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参数,也不应该是构造函数。

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

每个TMethodFilters返回的TSpecification<T>是一个带有运算符重载的记录,它产生布尔逻辑并将其分配给TPredicate<T>

使用规范模式会产生非常易读和可组合的代码,因为您可以将所有内容分开。循环不会与内部结构混杂,如何确定它是一个构造函数还是方法具有哪种参数,因为每个规范都被封装到它自己的类中。

P.S。 Methods是来自Spring.Helpers的TRttiTypeHelper的属性,返回IEnumerable<TRttiMethod>