Attributes

You can think of attributes as annotations that can be applied to certain pieces of code to provide additional information either to the compiler or to the program at runtime. Please refer to the Attributes topic in Language Concepts for a more in-depth coverage of what can be accomplished with attributes, and how to create your own.

Attributes are not code that executes per se, but they can influence the program in several ways:

  • They can instruct the compiler to adjust its behavior (for Special Attributes and for Aspects.
  • They can provide metadata that can be queried as the program runs.

In Oxygene, like C#, attributes use a square bracket syntax enclosing on or more attribute names. Each attribute can be optionally followed by a list of parameters enclosed in parenthesis. Just as with calls to Constructors with the new keyword, these can include regular parameters matching the attribute's constructor, and named parameters that will set properties of the attribute.

[Obsolete]

or

[Conditional('DEBUG')]

Attributes can be applied to many places in code by placing the attribute in front of the construct it applies to. This includes type declarations, type members, variables and method parameters.

Where ambiguities could occur, and to apply attributes to places that don't have a representation in code (such as globally to the whole assembly), optional prefixes can be provided, separated from the actual attribute name by a colon:

[write: Obsolete] // applies only to *writing* the property, not reading
property Foo: String;

or

[assembly: AssemblyTitle('My Project')] // applies to the whole assembly

The prefix here is optional and can be one of: * assembly: Apply to the assembly, only allowed in a global context *_odule: Apply to the .NET module, only allowed in a global context * field: Apply to the underlying field for a property * method: Apply to the Invoke method for delegates * main: Swift only, apply to the implied main method * param: Apply to the value parameter of a property setter * read: Apply to the read part of the property * write: Apply to the write part of the property * result: Apply to the return type of a method/property

Hydrogene, Silver and Iodine

Attributes are supported in all 4 languages. Hydrogene uses the same syntax as Oxygene (but with = instead of := for named parameters). Silver and Iodine uses a different syntax:

@prefix:AttributeType(Arguments, Name = value)

Where prefix is optional and can be one of: * __assembly: Apply to the assembly, only allowed in a global context *__module: Apply to the .NET module, only allowed in a global context * field: Apply to the underlying field for a property * method: Apply to the Invoke method for delegates * main: Swift only, apply to the implied main method * param: Apply to the value parameter of a property setter * return: Apply to the return type of a method/property

Defining new attribute types

.NET, Toffee and Island

Defining an attribute on .NET can be done by defining a subclass of System.Attribute (.NET), RemObjects.Elements.System.Attribute (Toffee) or RemObjects.Elements.System.Attribute (Island):

type
  [AttributeUsage(AttributeTargets.Class)] // only allowed on a class
  MyAttribute = public class(Attribute)
  public
    constructor(value: Integer);

    property Name: String;
  end;

  [MyAttribute(15, Name := 'Name')]
  MyClass = public class
  end;  
  [AttributeUsage(AttributeTargets.Class)] // only allowed on a class
  public class MyAttribute: Attribute
  {
    public MyAttribute(int value) { ... }

    public String Name { get;set; }
  }

  [MyAttribute(15, Name = 'Name')]
  public class MyClass
  {

  }
  @AttributeUsage(AttributeTargets.Class) // only allowed on a class
  public class MyAttribute: Attribute
  {
    public init (value: Integer) { ... }

    public var Name: String
  }

  @MyAttribute(15, Name = 'Name')
  public class MyClass
  {

  }

Java

Defining an attribute (what Java calls Annotation) for Java/Android can be done by defining a new interface that implements Annotation:

type
  [Retention(value := RetentionPolicy.RUNTIME)] // allow accessing them at runtime instead of just compiletime
  [Target(value := [ElementType.TYPE])] // allow on types
  MyAttribute = public interface(Annotation)
  public
    method value: Integer; // value is treated special and can be used as a non named parameter

    method Name: String;
  end;

  [MyAttribute(15, Name := 'Name')]
  MyClass = public class
  end;  
  [Retention(value = RetentionPolicy.RUNTIME)] // allow accessing them at runtime instead of just compiletime
  [Target(value = [ElementType.TYPE])] // allow on types
  public interface MyAttribute: Annotation
  {
    int value(); // value is treated special and can be used as a non named parameter
    string Name();
  }

  [MyAttribute(15, Name = 'Name')]
  public class MyClass
  {

  }
  @Retention(value = RetentionPolicy.RUNTIME) // allow accessing them at runtime instead of just compiletime
  @Target(value = [ElementType.TYPE]) // allow on types
  public protocol MyAttribute: Annotation
  {
    func value() -> Integer // value is treated special and can be used as a non named parameter
    func Name() -> String
  }

  @MyAttribute(15, Name = 'Name')
  public class MyClass
  {

  }

Supported Prefixes

The following prefixes are supported by Oxygene:

  • var: — apply the attribute to the backing field of a Property or Event.
  • read: — apply the attribute to the backing read statement of a Property.
  • result: — apply the attribute to the result of a Method or Property.
  • param: — apply the attribute to a parameter of a Method or Property.
  • write: — apply the attribute to the backing write statement of a Property.
  • global: — apply the attribute to the container type for Globals.
  • assembly: — apply the attribute to the whole assembly or executable.
  • module: — rarely used, apply the attribute to the current Module, on .NET.
  • aspect: — optional, designates that the attribute is implemented via an Aspect.

See Also

Version Notes

  • The param: and result: prefixes are new in Version 8.1.