我想查询我正在编写的类中的一些属性(也称为注释)。
我可以用复杂的方式做到这一点,但我想使用 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 的书)所需的无数行?
这些过滤器是使用规范模式实现的。 另请参见 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>
成为可能。
使用规范模式会产生非常可读且可组合的代码,因为您将所有内容分开。循环不会因内部如何确定它是否是构造函数或该方法具有什么类型的参数而变得混乱,因为每个规范都封装到自己的类中。
附注
Methods
是来自 Spring.Helpers 的 TRttiTypeHelper
的属性,它返回 IEnumerable<TRttiMethod>
。