Accessor macros - vilinski/nemerle GitHub Wiki

Field accessors

When writing classes, you very often need to write code like:

 mutable some_field : int; 

 public SomeField : int 
 {
   get { some_field }
 } 

You can automate this common pattern using the Accessor macro:

 using Nemerle.Utility;

[Accessor (SomeField)] mutable some_field : int; 

Here, the Accessor macro creates a read-only property named SomeField, which accesses the field {some_field}. Accessor properties are read-only by default.

You can also omit the name, in which case the property name will be based on the field name. The name will be capitalized, and underscores removed:

  • some_field is changed to SomeField

  • _my_longer_property becomes MyLongerProperty

This helps make property names more uniform and readable.

Option flags

There are three flag options available for this macro. The first is for specifying that the accessor is internal, not public. This limits accessibility to callers within the same assembly:

 [Accessor (SomeField, flags = Internal)] 
 mutable some_field : int;

// Equivalent to: 
mutable internal_field : int = 0 ; 

internal InternalField : int 
{
  get { internal_field }
} 

There are similar Protected, Virtual and Override options.

The WantSetter option is used to generate a set property:

 [Accessor (SomeField, flags = WantSetter)] 
 mutable some_field : int;

// Equivalent to: 
public SomeField : int 
{
  get { some_field }
  set { some_field = value }
} 

Flags can be combined:

[Accessor(SomeField, flags = Internal | WantSetter)]
mutable some_field : int; 

Option attributes

Sometimes, it is necessary to add some custom attributes to the generated property. Option attributes is used to solve this challenge:

 [Accessor (SomeField, attributes(System.CLSCompliant(true), AnyOther))] 
 mutable some_field : int;

// Equivalent to: 
[System.CLSCompliant(true), AnyOther] 
public SomeField : int 
{
  get { some_field }
} 

Flags accessors

There are cases when you want to use field of enum type (marked with System.Flags attribute) to store a set of flags. But you otherwise want this stuff to be exposed via boolean properties. For example:

 class SomeClass 
 {

         [System.Flags]
         enum MyFlags {
           | Is42        = 0x0001
           | Kopytko     = 0x0002
           | DeepThought = 0x0004
         }

         mutable state : MyFlags;

         public Is42 : bool
         {
           get { state %&& MyFlags.Is42 }
           set {
             if (value)
               state |= MyFlags.Is42
             else
               state &= ~MyFlags.Is42;
           }
         }

         // same for Kopytko and DeepThought

} 

There is FlagAccessor macro to automate this:

 using Nemerle.Utility;

class SomeClass {

         [System.Flags]
         enum MyFlags {
           | Is42        = 0x0001
           | Kopytko     = 0x0002
           | DeepThought = 0x0004
         }

         [FlagAccessor (Is42, flags = WantSetter)]
         [FlagAccessor (Kopytko, flags = WantSetter)]
         [FlagAccessor (DeepThought, flags = WantSetter)]
         mutable state : MyFlags;

} 

To shorten it even more you can group several flags in one macro invocation:

 using Nemerle.Utility;

class SomeClass 
{

         [System.Flags]
         enum MyFlags {
           | Is42        = 0x0001
           | Kopytko     = 0x0002
           | DeepThought = 0x0004
         }

         [FlagAccessor (Is42, Kopytko, DeepThought, flags = WantSetter)]
         mutable state : MyFlags;

}