NoesisGUI

Dynamic Classes

The Core/DynamicClass package allows for creating new types at runtime. The reflection information for this dynamic types is 100% compatible with the static reflection information implemented in the Core. This means that code that is supposed to work with reflection information (like for example a GUI component to edit properties) will work with DynamicClasses.

Creating a Dynamic Class

To create a dynamic class, first you have to register the properties that you are going to need. In this example I am going to use the following types: NsByte, NsUInt16, Ptr<Resource> and NsFloat32.

Ptr<BaseComponent> byteProperty = DynamicClass::RegisterType<NsByte>();
Ptr<BaseComponent> wordProperty = DynamicClass::RegisterType<NsUInt16>();
Ptr<BaseComponent> resourceProperty = DynamicClass::RegisterType<Ptr<Resource> >();
Ptr<BaseComponent> floatProperty = DynamicClass::RegisterType<NsFloat32>();

Now, that we have registered the types properties are added to a new dynamic class

// struct DynamicClass
//{
//    NsByte byte0;
//    NsUInt16 word;
//    Ptr<Resource> resource;
//    NsByte byte1;
//    NsFloat32 float[4];
//};

Ptr<DynamicClass> dynClass = NsCreateComponent<DynamicClass>(NSS(DynClass));
dynClass->AddProperty(NSS(byte0), byteProperty);
dynClass->AddProperty(NSS(word), wordProperty);
dynClass->AddProperty(NSS(resource), resourceProperty);
dynClass->AddProperty(NSS(byte1), byteProperty);
dynClass->AddPropertyArray(NSS(floats), floatProperty, 4);

Setting Default Values

Before creating instances from the dynamic class, we must set the default values for each property.

dynClass->Set<NsByte>(NSS(byte0), 32);
dynClass->Set<NsUInt16>(NSS(word), 44);

Ptr<Resource> resource = NsCreateComponent<Resource>(500.0f, 600.0f);
dynClass->Set<Ptr<Resource> >(NSS(resource), resource);

dynClass->Set<NsByte>(NSS(byte1), 192);
dynClass->Set<NsFloat32>(NSS(floats), 0, 0.0f);
dynClass->Set<NsFloat32>(NSS(floats), 1, 1.0f);
dynClass->Set<NsFloat32>(NSS(floats), 2, 2.0f);
dynClass->Set<NsFloat32>(NSS(floats), 3, 3.0f);

Creating instances

Once the dynamic class is properly configured, you can create an instance and Set/Get properties.

Ptr<DynamicClassInstance> instance = dynClass->CreateInstance();

/// Set properties
instance->Set<NsByte>(NSS(byte0), 240);
instance->Set<NsUInt16>(NSS(word), 1045);

Ptr<Resource> resource = NsCreateComponent<Resource>(1500.0f, 1600.0f);
instance->Set<Ptr<Resource> >(NSS(resource), resource);

instance->Set<NsByte>(NSS(byte1), 12);
instance->Set<NsFloat32>(NSS(floats), 0, 10.0f);
instance->Set<NsFloat32>(NSS(floats), 1, 11.0f);
instance->Set<NsFloat32>(NSS(floats), 2, 12.0f);
instance->Set<NsFloat32>(NSS(floats), 3, 13.0f);

/// Get properties
NsByte byte0 = instance->Get<NsByte>(NSS(byte0));
NsUInt16 word = instance->Get<NsUInt16>(NSS(word));
Ptr<Resource> resource = instance->Get<Ptr<Resource>>(NSS(resource));
NsByte byte1 = instance->Get<NsByte>(NSS(byte1));
NsFloat32 float0 = instance->Get<NsFloat32>(NSS(floats), 0);
NsFloat32 float1 = instance->Get<NsFloat32>(NSS(floats), 1);
NsFloat32 float2 = instance->Get<NsFloat32>(NSS(floats), 2);
NsFloat32 float3 = instance->Get<NsFloat32>(NSS(floats), 3);

Serializing / Unserializing

Both dynamic classes and instances can be serialized as a normal type.

{
    // class serialization
    Ptr<ISerializationManager> sm = NsCreateComponent(NSS(SerializationManager));
    Ptr<IStream> stream = NsCreateComponent(NSS(MemoryStream));
    {
        sm->SerializeBegin(stream);
        sm->Serialize(dynClass);
        sm->SerializeEnd();
    }


    // instance serialization
    Ptr<ISerializationManager> sm = NsCreateComponent(NSS(SerializationManager));
    Ptr<IStream> stream = NsCreateComponent(NSS(MemoryStream));
    {
        sm->SerializeBegin(stream);
        sm->Serialize(instance);
        sm->SerializeEnd();
    }
}

Reflection information

As said above, Dynamic Classes store reflection information that is compatible with the the static reflection supported by Noesis.

const TypeClass* type = instance->GetType();

NS_UNITTEST_CHECK(type ->GetNumProperties() == 5);
const TypeProperty* typeProperty = typeClass->GetProperty(0);
NS_UNITTEST_CHECK(typeProperty->GetContentType() == TypeOf<NsByte>::Get());
© 2017 Noesis Technologies