C# Reflexion & Attributes to C++

I develop a software for urban planing oriented ecology. Initially Polaris is a CAD software (similar to AutoCAD or MicroStation) with tools about geomatics engineering and earthwork engineering. So this software may be also used to compute the thermal performance of the building. My work concerns especially generic programming to improve software and a project of rainwater sanitation simulation with pollution aspect. In a word, Polaris use C# code, even through I consider myself as a C++ developer.

I think C# language proposes an interesting syntactic sugar around the code with Attributes. So, what is an attribute and how create this with C++.

C# Attribute

An attribute adds information to properties, methods or classes. These information can be used by the reflexion mechanism. The following example concerns an object with tree accessible properties and the aim is just to display the values with associated text.

class MyCounter
{
  [InformationAttribute("value of the counter")]
  public int Value {get; private set;}

  [InformationAttribute("minimal value of the counter")]
  public int Min {get; private set;}

  [InformationAttribute("maximal value of the counter")]
  public int Max {get; private set;}

  public void Incr()
  {
    Value++;
    if(Value>Max) Max = value;
  }

  public void Decr()
  {
    Value--;
    if(Value<Min) Min = value;
  }

  public MyCounter(int initialValue)
  {
     Value = Min =Max = initialValue;
  }
}
C# MyCounter

The code which displays the three values is:

public void Display(object obj)
{
  PropertyInfo[] props = obj.getType().GetProperties();
  foreach (PropertyInfo prop in props)
  {
    object[] attrs = prop.GetCustomAttributes(true);
    foreach (object attr in attrs)
    {
      InformationAttribute ia = attr as InformationAttribute;
      if (ia != null)
      {
        string value = prop.GetValue(obj).ToString();
        string text = authAttr.Text;
          
        System.Console.WriteLine( text + ": " + value );
      }
    }
  }
}
C# display method

An the output of the method (with a MyCounter) may be:

value of the counter: 20
minimal value of the counter: -5
maximal value of the counter: 23
Output

The advantage of this code is to use the same method to display information of many different type. The description of the class is sufficient and the developer doesn't need to develop specific method for each object. An use of the reflexion mechanism may be to create graphical user interface: personally, I think forms design is a waste of time and I prefer work on computational mechanisms.

C++ version

When I have begun my project Imbricable, I have considered this way and I have copied an idea which I have found during my thesis in the Sofa-Framework. So, I have created tree classes which correspond to accessors, attribute and a container of accessors. The equivalent of the MyCounter class using a mechanism as the one developed in my project may be:

class MyCounter::BaseObject
{
    static Metadata meta_value;
    static Metadata meta_min;
    static Metadata meta_max;

protected:
    static Data<int> data_value;
    static Data<int> data_max;
    static Data<int> data_min;

public:
     MyCounter();
     void incr();
     void decr();
}
C++ header of MyCounter class
#include "mycounter.h"

Metadata MyCounter::meta_value("value of the counter");
Metadata MyCounter::meta_min("minimal value of the counter");
Metadata MyCounter::meta_max("maximal value of the counter");

MyCounter::MyCounter(int intialValue), BaseObject(),
  data_value(new Data<int>(this, initialValue, &data_value) ),
  data_min(new Data<int>(this, initialValue, &data_min) )
  data_min(new Data<int>(this, initialValue, &data_max) )
{
}

MyCounter::incr()
{
  int value = data_value.get();
  data_value.set(++value);
  if(value>data_max.get())data_max.set(value);
}

MyCounter::decr()
{
  int value = data_value.get();
  data_value.set(++value);
  if(value<data_min.get())data_min.set(value);
}
C++ source of the MyCounter class

Metadata (attribute) are defined as static because this is the behavior of C# attributes and the attributes are not runtime modifiable. A no-static object should cause an avoidable memory consumption due to duplication of the text.

Data is a template/generic class which inherit from a undefined accessors class (BaseData).

And the equivalent of the display method:

void display(BaseObject obj)
{
  for(int i=0; i<obj.dataListSize(); i++)
  {
    BaseData* data = obj.getData(i);
    Metadata* meta = data.metadata();
    std::cout << meta->text() << ": " << data->toString() << std::endl; 
  }
}
C++ display method

So the mechanism requires the next classes to work:

class Metadata
{
  string _text;
public:
  Metadata(string txt){_text = txt;}
  string text(){return _text;}
}
Metadata
class BaseData
{
  Metadata *_metadata;
public:
  BaseData(Metadata *meta){_metadata = meta;}
  Metadata * metadata{return _metadata;}
  virtual string toString()=0;
}

template<class C>
class Data:: public BaseData
{
   C _value;
public:
   Data(BaseObject parent, C value, Metadata *meta):BaseData(meta){_value = value; parent.addToDataList(this)};
   C get(){return _value;}
   void set(C value){_value=value;}
}
Data

Note: The method toString() should be override depending the used template (here Data<int>::toString() must describe the int/string conversion).

Conclusion:

The C# syntactic sugar which concerns attribute is not difficult to recreate. Nevertheless, it is dependent of the reflexion and each properties may be registered to the object. In my project, I have added smart pointer (and the fact to share value), link to other object and attribute for methods. The main use of this mechanism concerns the user interface creation and the XML serialization.