Attributes or Annotated programming
Atributes are a feature that enable you to "annotate" your classes, class members and parameters with additional info that can be useful in your programming context.
The .NET Runtime use thoroughly attributes for things like importing external functions (DllImport), declaring the layout of classes (StructLayout), the marshaling behaviour of parameters, threading behavior (ThreadStatic) and more.
Depending of the attribute it could be merely decorative or it may alter significantly the way the .NET Runtime treats the target element of the attribute.
An attribute can be applied to classes, class members and other elements.
To apply an attribute you use the following syntax:.
[System::CLSCompliant];
DEFINE CLASS TestClass
nProperty as integer
PROCEDURE MyMethod
TPARAMETERS tcInfo as string
ENDDEFINE
See the semicolon (;) at the end of the attribute because it is joined to the target element (class) , without the semi
colon the Compiler will throw an error.
Attributes applied to methods
You may also use attributes to annotate methods. For example, the DllImport attribute is used to import an external function residing in an external DLL. Use this syntax to annotate your method:.
[DllImport("DllName.DLL",EntryPoint = "FunctionNameInDLL")] ;
static HIDDEN PROCEDURE FunctionNameInVFP as integer
TPARAMETERS tnValue as integer
As you see an attribute can also have some parameters depending of the constructor signature and named arguments as the EntryPoint. Usually you only need to specify the "DllName.dll" because the FunctionName if not specified is the same name as declared in VFP (i.e. FunctionNameInVFP).
For more information about the DllImport look here.
If you need more than one attribute you can apply several using the syntax:
[MyAttribute1(),MyAttribute2()];
Attributes applied to parameters
You apply an attribute to a parameter by writing the attribute before the parameter name. For example to set the marshaling behavior for a parameter instead of being the default (Unicode) to AnsiBSTR you would write:
PROCEDURE MyMethod
TPARAMETERS [MarshalAs(UnmanagedType::AnsiBStr)] tcvalue as string
Attributes applied to fields
For fields you write the attibute fefore the field name. To declare that a field will use Thread Local Storage you use:
DEFINE CLASS TestClass
[System::ThreadStatic];
static @MyField as string = ""
ENDDEFINE