Attaching Attributes 

Visual J# allows you to attach attributes to classes, fields, methods, parameters, and other programming elements. Both custom attributes and pseudo attributes (attributes that you cannot query for via Reflection) can be attached to the metadata. Visual J# follows the Visual J++ extension syntax to allow attaching attributes to the metadata.

To attach an attribute, use the @attribute directive followed by the name of the attribute that is to be attached. If an attribute parameter accepts any type object, you must pass the underlying class object as the argument instead of casting it to a type Object.

Attributes are attached to return types using the @attribute.return directive, and can be targeted for the underlying method using the @attribute.method directive.

It is an error to attach these directives for programming elements other than those specified. For all other attributes, the compiler determines the target by the member following the directive.

The following example shows how to use @attribute:

// vjc_attributes1.jsl
// compile with: /target:library
import System.*;
import System.Runtime.InteropServices.*;
public class MyClass
{
    /** @attribute DllImport("user32", CharSet=CharSet.Ansi) */
    public static native int MessageBox(
        int hwnd, 
        /** @attribute MarshalAs(UnmanagedType.AnsiBStr)*/
        System.String title, 
        System.String caption,
        int type);
}

The following example shows how to use @attribute.return to specify marshaling attributes on a return type.

// vjc_attributes2.jsl
// compile with: /target:library
import System.Runtime.InteropServices.*;
public class MyClass
{
    /** @attribute.return MarshalAs(UnmanagedType.LPArray, SizeConst=10) */
    int[] getBytes()
    {
        int arr[] = {1,2};
        return arr;
    }
}

The following example shows how to use @attribute.method to specify marshaling attributes on a return type.

// vjc_attributes3.jsl
// compile with: /target:library
import System.*;
public class MyClass
{
    /** @property */
    /** @attribute.method Obsolete("get_Bytes is deprecated", false) */
    // The directive ensures that the attribute is attached to the method.
    int[] get_Bytes()
    {
        int arr[] = {1,2};
        return arr;
    }
}

You cannot define an attribute in your Visual J# program; you can only consume attributes from the .NET Framework or other referenced assemblies.

Assembly level attributes are attached using the @assembly directive instead of the @attribute directive. The @assembly directive must be at the beginning of the file following the package and import statements, if any.

import System.Reflection.*;
/** @assembly AssemblyTitle("My Assembly") */
/** @assembly AssemblyCompany("My Company") */

The grammar for attributes is as follows:

Term Definition

Attributes

attribute-sections

attribute-sections

attribute-section

attribute-sections attribute-section

attribute-section

/** attribute-list */

attribute-list

newlineopt attribute newlineopt

attribute-list newline attribute

Attribute

attribute-target-specifier attribute-name attribute-arguments

attribute-target-specifier

@attribute

@assembly

@attribute.return

@attribute.method

attribute-name

type-name

attribute-arguments

( positional-argument-listopt )

( positional-argument-list , named-argument-list )

( named-argument-list )

positional-argument-list

positional-argument

positional-argument-list , positional-argument

positional-argument

attribute-argument-expression

named-argument-list

named-argument

named-argument-list , named-argument

named-argument

attribute-sections

attribute-argument-expression

attribute-section

attribute-sections attribute-section

  • Attributes can be attached to classes, fields, methods, or method parameters.

  • Attributes must start at the beginning of a line.

  • An asterisk (*) is treated as a whitespace in the list following the start of the comment. Similarly, a new-line character (\n) is also whitespace between the keywords or arguments.

  • Commas separate arguments.

  • The type name following the @attribute-target-specifier must resolve to an attribute type in the current context. You can either give a fully qualified class name or just a simple class name in which case the import information is used to resolve the type. Similarly the identifier in the named argument must correspond to a property or field in the attribute type.

  • By convention, attribute classes are named with a suffix of Attribute. An attribute-name of the form type-name may either include or omit this suffix.

    /** @attribute STAThreadAttribute() */ // refers to STAThreadAttribute
    public static void main(String [] args) {}
    // The Attribute suffix is optional
    /** @attribute STAThread() */ // Also refers to STAThreadAttribute
    public static void main(String [] args) {}
    
  • If a parameter to an attribute is a Type object then you should pass the underlying class object as an argument.

Show: