Reflection
Key takeaways
Reflection | The capacity of code to introspect. |
Reflect | PIP.Services package with reflection functionality. |
MethodReflector | Component used to examine an object's methods and to dynamically invoke them. |
ObjectReader | Component used to examine the properties of an object and to dynamically read them. |
ObjectWriter | Component used to dynamically set the properties of an object. |
PropertyReflector | Component used to examine an object's properties and to dynamically get and set their values. |
RecursiveObjectReader | Component used to examine the properties of an object and to dynamically read them recursively using "dot" notation. |
RecursiveObjectWriter | Component used to dynamically set the properties of an object in a recursive way using "dot" notation. |
Introduction
In this tutorial, you will learn how to use the Reflect package. This package provides different classes that will allow you to develop code with introspection capacity. We will start by briefly describing reflection. Then, we will learn how to use each of the different components provided in the package through the use of examples.
What is reflection?
Reflection is a feature available in PIP. Services through its Reflect package. It allows a running microservice to examine and manage its internal properties. For example, given a class, it helps us to obtain the names of all its methods or the values of its parameters. In order to understand this package, we will go through its main classes and explain how they work.
The Reflect package
This package belongs to the commons module and contains several classes used to examine objects dynamically.
a) MethodReflector
The MethodReflector class allows us to examine an object’s methods and to execute them dynamically. The get_method_names method returns a list with all the methods in a class. The has_method method returns a boolean indicating whether or not a method belongs to a class. And, the invoke_method provides a way to invoke the execution of a method at runtime. The example below shows how to obtain the names of all methods in an object, find out if a method belongs to that object, and invoke its execution.
import { MethodReflector } from "pip-services4-commons-node";
export class ClassA {
public methodA(): number {
return 123;
}
public methodB() {
console.log("hello world b")
}
}
export function main() {
let myClassA = new ClassA();
// Obtain all methods in classA
let methods1 = MethodReflector.getMethodNames(myClassA);
console.log("The methods in myClassA are: ", methods1);
// Ask whether a specific method exists or not
let methods2 = MethodReflector.hasMethod(myClassA, "methodA");
console.log("methodA belongs to myClassA: ", methods2);
let methods3 = MethodReflector.hasMethod(myClassA, "methodC");
console.log("methodC belongs to myClassA: ", methods3);
// Invoke a method in classA
let methods4 = MethodReflector.invokeMethod(myClassA, "methodA");
console.log("After running methodA the result is: ", methods4);
}
// Method Reflector
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
type ObjectA struct {
}
func (c *ObjectA) MethodA() int {
return 123
}
func (c *ObjectA) MethodB() {
fmt.Println("hello world b")
}
func main() {
myObjectA := &ObjectA{}
// Obtain all methods in ObjectA
methods1 := creflect.MethodReflector.GetMethodNames(myObjectA)
fmt.Println("The methods in myObjectA are: ", methods1)
// Ask whether a specific method exists or not
methods2 := creflect.MethodReflector.HasMethod(myObjectA, "methodA")
fmt.Println("methodA belongs to myObjectA: ", methods2)
methods3 := creflect.MethodReflector.HasMethod(myObjectA, "methodC")
fmt.Println("methodC belongs to myObjectA: ", methods3)
// Invoke a method in ObjectA
methods4 := creflect.MethodReflector.InvokeMethod(myObjectA, "methodA")
fmt.Println("After running methodA the result is: ", methods4)
}
# Method Reflector
from pip_services4_commons.reflect import MethodReflector
class classA:
def methodA(self):
return 123
def methodB(self):
print("hello world b")
my_classA = classA()
# Obtain all methods in classA
methods1 = MethodReflector.get_method_names(my_classA)
print("The methods in my_classA are: ", methods1)
# Ask whether a specific method exists or not
methods2 = MethodReflector.has_method(my_classA, "methodA")
print("methodA belongs to my_classA: ", methods2)
methods3 = MethodReflector.has_method(my_classA, "methodC")
print("methodC belongs to my_classA: ", methods3)
# Invoke a method in classA
methods4= MethodReflector.invoke_method(my_classA, "methodA")
print("After running methodA the result is: ", methods4)
After running the above code, we will get the following output:
![figure 1](figure1.png)
b) ObjectReader
This class helps us to investigate the properties of an object. Its get_property_names method returns a list of the properties in a class. The get_property method is used to obtain the value of a property, and the get_properties method reads the properties of an object and returns a map (dictionary) with their names and values. The code below shows examples of their usage.
import { ObjectReader } from "pip-services4-commons-node";
export class ClassA {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export function main() {
let myClassA = new ClassA();
// Obtain all properties in ClassA
let properties = ObjectReader.getPropertyNames(myClassA);
console.log("The properties in myClassA are: ", properties);
// Obtain the value of a property in classA
let value1 = ObjectReader.getProperty(myClassA, "param1");
console.log("The value of param1 is: ", value1);
let value2 = ObjectReader.getProperties(myClassA);
console.log("The properties and values in myClassA are: ", value2);
}
// Object reader
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
type ObjectA struct {
Param1 string
Param2 int
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
}
}
func (c *ObjectA) MethodA() int {
return 123
}
func main() {
myObjectA := NewObjectA()
// Obtain all properties in ObjectA
properties := creflect.ObjectReader.GetPropertyNames(myObjectA)
fmt.Println("The properties in myObjectA are: ", properties)
// Obtain the value of a property in myObjectA
value1 := creflect.ObjectReader.GetProperty(myObjectA, "Param1")
fmt.Println("The value of Param1 is: ", value1)
value2 := creflect.ObjectReader.GetProperties(myObjectA)
fmt.Println("The properties and values in myObjectA are: ", value2)
}
# Object reader
from pip_services4_commons.reflect import ObjectReader
class classA:
param1 = "hello"
param2 = 123
def methodA(self):
return 123
my_classA = classA()
# Obtain all properties in classA
properties = ObjectReader.get_property_names(my_classA)
print("The properties in my_classA are: ", properties)
# Obtain the value of a property in classA
value1 = ObjectReader.get_property(my_classA, "param1")
print("The value of param1 is: ", value1)
value2 = ObjectReader.get_properties(my_classA)
print("The properties and values in my_classA are: ", value2)
Once the code above is executed, we will get the following result:
![figure 2](figure2.png)
The methods in this component can also be used with maps and arrays to find out if they contain certain elements and their values.
export function main() {
// Obtain properties from a map(dictionary)
let myMap = { 'key1': 123, 'key2': "ABC" };
let hasProperty1 = ObjectReader.hasProperty(myMap, "key1");
let value1 = ObjectReader.getProperty(myMap, "key1");
console.log("MyMap contains key1: ", hasProperty1);
console.log("The value of key1 is : ", value1);
// Obtain properties from an array
let myArray = [1, 2, 3];
let hasProperty2 = ObjectReader.hasProperty(myArray, "5");
let hasProperty3 = ObjectReader.hasProperty(myArray, "0");
let value2 = ObjectReader.getProperty(myArray, "0");
console.log("myArray contains an element with index 5: ", hasProperty2);
console.log("myArray contains an element with index 0: ", hasProperty3);
console.log("The value stored at postion 0 is: ", value2);
}
// Obtain properties from a map (dictionary)
myMap := map[string]interface{}{"key1": 123, "key2": "ABC"}
hasProperty1 := creflect.ObjectReader.HasProperty(myMap, "key1")
value1 := creflect.ObjectReader.GetProperty(myMap, "key1")
fmt.Println("MyMap contains key1: ", hasProperty1)
fmt.Println("The value of key1 is : ", value1)
// Obtain properties from an array
myArray := []int{1, 2, 3}
hasProperty2 := creflect.ObjectReader.HasProperty(myArray, "5")
hasProperty3 := creflect.ObjectReader.HasProperty(myArray, "0")
value2 := creflect.ObjectReader.GetProperty(myArray, "0")
fmt.Println("myArray contains an element with index 5: ", hasProperty2)
fmt.Println("myArray contains an element with index 0: ", hasProperty3)
fmt.Println("The value stored at postion 0 is: ", value2)
# Obtain properties from a map (dictionary)
myMap = { 'key1': 123, 'key2': "ABC" }
has_property1 = ObjectReader.has_property(myMap, "key1")
value1 = ObjectReader.get_property(myMap, "key1")
print("MyMap contains key1: ", has_property1)
print("The value of key1 is : ", value1)
# Obtain properties from an array
myArray = [1, 2, 3]
has_property2 = ObjectReader.has_property(myArray, "5")
has_property3 = ObjectReader.has_property(myArray, "0")
value2 = ObjectReader.get_property(myArray, "0")
print("myArray contains an element with index 5: ", has_property2)
print("myArray contains an element with index 0: ", has_property3)
print("The value stored at postion 0 is: ", value2)
c) ObjectWriter
This component helps us to dynamically set the properties of an object. Its set_property method can be used to set the value of the property of an object at runtime. Similarly, the set_propeties method allows us to set the values of some or all the properties of an object with an input defined as a map. These methods can also be used with common objects such as maps and arrays.
import { ObjectReader, ObjectWriter } from "pip-services4-commons-node";
export class ClassA {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export function main(){
let myClassA = new ClassA()
let value1 = ObjectReader.getProperty(myClassA, "param1");
console.log("The value of param1 is: ", value1);
ObjectWriter.setProperty(myClassA, "param1", "hello 2");
let value2 = ObjectReader.getProperty(myClassA, "param1");
console.log("The new value of param1 is: ", value2);
let myMap1 = { 'param1': 123, 'param2': "ABC" };
ObjectWriter.setProperties(myClassA, myMap1);
let value3 = ObjectReader.getProperties(myClassA);
console.log("The new parameter values are: ", value3);
// Map(dictionary)
let myMap2 = { 'key1': 123, 'key2': "ABC" };
ObjectWriter.setProperties(myMap2, { 'key1': 15422, 'key2': "ab" });
let value4 = ObjectReader.getProperties(myMap2);
console.log("The new values in the map are : ", value4);
let myMap3 = { 'key1': 123, 'key2': "ABC" };
ObjectWriter.setProperty(myMap3, "key1", "XYZ");
value2 = ObjectReader.getProperty(myMap3, "key1");
console.log("The new value in the map is : ", value2);
// Array
let myArray = [1, 2, 3];
ObjectWriter.setProperty(myArray, "0", 123);
value3 = ObjectReader.getProperty(myArray, "0");
console.log("The new value in the array is : ", value3);
}
// Object writer - Setting property values
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
Param1 string
Param2 int
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
}
}
func (c *ObjectA) MethodA() int {
return 123
}
func main() {
myObjectA := NewObjectA()
value1 := creflect.ObjectReader.GetProperty(myObjectA, "Param1")
fmt.Println("The value of param1 is: ", value1)
creflect.ObjectWriter.SetProperty(myObjectA, "Param1", "hello 2")
value2 := creflect.ObjectReader.GetProperty(myObjectA, "Param1")
fmt.Println("The new value of param1 is: ", value2)
// Map (dictionary)
myMap := map[string]interface{}{"key1": 123, "key2": "ABC"}
creflect.ObjectWriter.SetProperties(myMap, map[string]interface{}{"key1": 15422, "key2": "ab"})
value4 := creflect.ObjectReader.GetProperties(myMap)
fmt.Println("The new values in the map are : ", value4)
myMap = map[string]interface{}{"key1": 123, "key2": "ABC"}
creflect.ObjectWriter.SetProperty(myMap, "key1", "XYZ")
value2 = creflect.ObjectReader.GetProperty(myMap, "key1")
fmt.Println("The new value in the map is : ", value2)
// Array
myArray := []int{1, 2, 3}
creflect.ObjectWriter.SetProperty(myArray, "0", 123)
value3 := creflect.ObjectReader.GetProperty(myArray, "0")
fmt.Println("The new value in the array is : ", value3)
}
# Object writer - Setting property values
from pip_services4_commons.reflect import ObjectWriter, ObjectReader
# Class
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
my_classA = classA()
value1 = ObjectReader.get_property(my_classA, "param1")
print("The value of param1 is: ", value1)
ObjectWriter.set_property(my_classA, "param1", "hello 2")
value2 = ObjectReader.get_property(my_classA, "param1")
print("The new value of param1 is: ", value2)
myMap = { 'param1': 123, 'param2': "ABC" }
ObjectWriter.set_properties(my_classA, myMap)
value3 = ObjectReader.get_properties(my_classA)
print("The new parameter values are: ", value3)
# Map (dictionary)
myMap = { 'key1': 123, 'key2': "ABC" }
ObjectWriter.set_properties(myMap, { 'key1': 15422, 'key2': "ab" })
value4 = ObjectReader.get_properties(myMap)
print("The new values in the map are : ",value4)
myMap = { 'key1': 123, 'key2': "ABC" }
ObjectWriter.set_property(myMap, "key1", "XYZ")
value2 = ObjectReader.get_property(myMap, "key1")
print("The new value in the map is : ", value2)
# Array
myArray = [1, 2, 3]
ObjectWriter.set_property(myArray, "0", 123)
value3 = ObjectReader.get_property(myArray, "0")
print("The new value in the array is : ", value3)
After running the above code, we will get the following result:
![figure 4](figure4.png)
d) PropertyReflector
This class allows us to examine an object’s properties and to dynamically get and set their values. The get_property_names is used to obtain a list containing all the properties of an object. The has_property method allows us to find out whether an object has a property or not. The get_properties method obtains all the properties of an object and their values and places the result in the form of a dictionary. And, the set_property method is used to set the value of an object’s property. The code below provides examples of these methods.
import { PropertyReflector } from "pip-services4-commons-node";
export class ClassA {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export function main(){
let myClassA = new ClassA();
// Obtain all property names
let properties = PropertyReflector.getPropertyNames(myClassA);
console.log("The properties of myClassA are: ", properties);
// Find out whether an object has a property or not
let has_param1 = PropertyReflector.hasProperty(myClassA, "param1");
console.log("ClassA contains param1: ", has_param1);
// Obtain all property names and their values
let value3 = PropertyReflector.getProperties(myClassA);
console.log("The properties of myClassA are: ", value3);
// Change the value of a parameter
let value1 = PropertyReflector.getProperty(myClassA, "param2");
PropertyReflector.setProperty(myClassA, "param2", 14785);
let value2 = PropertyReflector.getProperty(myClassA, "param2");
console.log("The value of param2 is: ", value1);
console.log("The new value of param2 is: ", value2);
}
// Property reflector
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
Param1 string
Param2 int
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
}
}
func (c *ObjectA) MethodA() int {
return 123
}
func main() {
myObjectA := NewObjectA()
// Obtain all property names
properties := creflect.PropertyReflector.GetPropertyNames(myObjectA)
fmt.Println("The properties of myObjectA are: ", properties)
// Find out whether an object has a property or not
hasParam1 := creflect.PropertyReflector.HasProperty(myObjectA, "Param1")
fmt.Println("ClassA contains param1: ", hasParam1)
// Obtain all property names and their values
value3 := creflect.PropertyReflector.GetProperties(myObjectA)
fmt.Println("The properties of myObjectA are: ", value3)
// Change the value of a parameter
value1 := creflect.PropertyReflector.GetProperty(myObjectA, "Param2")
creflect.PropertyReflector.SetProperty(myObjectA, "param2", 14785)
value2 := creflect.PropertyReflector.GetProperty(myObjectA, "Param2")
fmt.Println("The value of param2 is: ", value1)
fmt.Println("The new value of param2 is: ", value2)
}
# Property reflector
from pip_services4_commons.reflect import PropertyReflector
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
my_classA = classA()
# Obtain all property names
properties = PropertyReflector.get_property_names(my_classA)
print("The properties of my_classA are: ", properties)
# Find out whether an object has a property or not
has_param1 = PropertyReflector.has_property(my_classA, "param1")
print("ClassA contains param1: ", has_param1)
# Obtain all property names and their values
value3 = PropertyReflector.get_properties(my_classA)
print("The properties of my_classA are: ", value3)
# Change the value of a parameter
value1 = PropertyReflector.get_property(my_classA, "param2")
PropertyReflector.set_property(my_classA, "param2", 14785)
value2 = PropertyReflector.get_property(my_classA, "param2")
print("The value of param2 is: ", value1)
print("The new value of param2 is: ", value2)
After running the above code, we will get the following results.
![figure 5](figure5.png)
e) RecursiveObjectReader
This class helps us to examine the properties of an object and to dynamically read them using dot notation (object.subobject.property). The get_property_names gives a list containing all the properties in an object, and the has_property method returns a Boolean that indicates whether an object contains a property or not. The get_properties method provides us with a map containing all the properties of an object and their values, and the get_property method is used to obtain the value of a specific property.
The example below shows how to use this component. As we can see from the results obtained, when we apply the get_properties method to my_classB, we also obtain the parameters inherited from my_classA and their values.
import { RecursiveObjectReader } from "pip-services4-commons-node";
export class ClassAa {
public param5: string = "hello aa";
}
export class ClassA extends ClassAa {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export class ClassB extends ClassA {
public param4: string = "inside 2";
}
export function main(){
let myClassA = new ClassA();
let myClassB = new ClassB();
let value1 = RecursiveObjectReader.getPropertyNames(myClassA)
console.log("The property names of myClassA are: ", value1)
let value2 = RecursiveObjectReader.hasProperty(myClassB, "param5")
console.log("myClassB contains param5: ", value2)
let value3 = RecursiveObjectReader.getProperties(myClassB)
console.log("The properties of myClassB are: ", value3)
let value4 = RecursiveObjectReader.getProperty(myClassB, "param4")
console.log("The value of param4 is: ", value4)
}
// Recursive Object Reader
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
ObjectAa
Param1 string
Param2 int
}
type ObjectAa struct {
Param5 string
}
func (c *ObjectA) MethodA() int {
return 123
}
type ObjectB struct {
*ObjectA
Param4 string
}
func NewObjectB() *ObjectB {
return &ObjectB{
ObjectA: NewObjectA(),
Param4: "inside 2",
}
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
ObjectAa: ObjectAa{
Param5: "hello aa",
},
}
}
func main() {
myObjectA := NewObjectA()
myObjectB := NewObjectB()
value1 := creflect.RecursiveObjectReader.GetPropertyNames(myObjectA)
fmt.Println("The property names of myObjectA are: ", value1)
value2 := creflect.RecursiveObjectReader.HasProperty(myObjectB, "param5")
fmt.Println("myObjectB contains param5: ", value2)
value3 := creflect.RecursiveObjectReader.GetProperties(myObjectB)
fmt.Println("The properties of myObjectB are: ", value3)
value4 := creflect.RecursiveObjectReader.GetProperty(myObjectB, "Param4")
fmt.Println("The value of param4 is: ", value4)
}
# RecursiveObjectReader
from pip_services4_commons.reflect import RecursiveObjectReader
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
class classAa():
param5 = "hello aa"
class classB(classA):
param4 = "inside 2"
my_classA = classA()
my_classB = classB()
value1 = RecursiveObjectReader.get_property_names(my_classA)
print("The property names of my_classA are: ", value1)
value2 = RecursiveObjectReader.has_property(my_classB, "param5")
print("my_classB contains param5: ", value2)
value3 = RecursiveObjectReader.get_properties(my_classB)
print("The properties of my_classB are: ", value3)
value4 = RecursiveObjectReader.get_property(my_classB, "param4")
print("The value of param4 is: ", value4)
![figure 6](figure6.png)
f) RecursiveObjectWriter
This class is used to dynamically set the properties of an object recursively using dot notation. Its set_property method allows us to set the value of a property. The set_properties method is used to set the values of some or all the properties in an object and accepts a dictionary as input. The copy_properties method copies the properties of one object into another one. This code shows examples of their usage:
import { RecursiveObjectReader, RecursiveObjectWriter } from "pip-services4-commons-node";
export class ClassAa {
public param5: string = "hello aa";
}
export class ClassA extends ClassAa {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export class ClassB extends ClassA {
public param4: string = "inside 2";
}
export function main(){
let myClassB = new ClassB();
let myClassC = new ClassB();
// set_property
RecursiveObjectWriter.setProperty(myClassB, "param2", "new value");
let value1 = RecursiveObjectReader.getProperty(myClassB, "param2");
console.log("The new values for the myClassB object are:", value1);
// set_properties
let myMap = { 'param1': 789456, 'param2': "ABCaccc" };
RecursiveObjectWriter.setProperties(myClassB, myMap);
let value2 = RecursiveObjectReader.getProperties(myClassB);
console.log("The new values for the myClassB object are:", value2);
// copy_proerties
let value3 = RecursiveObjectReader.getProperties(myClassC);
console.log("The properties of myClassC and their values are:", value3);
RecursiveObjectWriter.copyProperties(myClassC, myClassB);
let value4 = RecursiveObjectReader.getProperties(myClassC);
console.log("The new properties of myClassC and their values are:", value4);
}
// RecursiveObjectWriter
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
ObjectAa
Param1 string
Param2 int
}
type ObjectAa struct {
Param5 string
}
func (c *ObjectA) MethodA() int {
return 123
}
type ObjectB struct {
*ObjectA
Param4 string
}
func NewObjectB() *ObjectB {
return &ObjectB{
ObjectA: NewObjectA(),
Param4: "inside 2",
}
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
ObjectAa: ObjectAa{
Param5: "hello aa",
},
}
}
func main() {
myObjectB := NewObjectB()
myObjectC := NewObjectB()
// set_property
creflect.RecursiveObjectWriter.SetProperty(myObjectB, "Param2", "new value")
value1 := creflect.RecursiveObjectReader.GetProperty(myObjectB, "Param2")
fmt.Println("The new values for the myObjectB object are:", value1)
// set_properties
myMap := map[string]interface{}{"Param1": 789456, "Param2": "ABCaccc"}
creflect.RecursiveObjectWriter.SetProperties(myObjectB, myMap)
value2 := creflect.RecursiveObjectReader.GetProperties(myObjectB)
fmt.Println("The new values for the myObjectB object are:", value2)
// copy_proerties
value3 := creflect.RecursiveObjectReader.GetProperties(myObjectC)
fmt.Println("The properties of myObjectC and their values are:", value3)
creflect.RecursiveObjectWriter.CopyProperties(myObjectC, myObjectB)
value4 := creflect.RecursiveObjectReader.GetProperties(myObjectC)
fmt.Println("The new properties of myObjectC and their values are:", value4)
}
# RecursiveObjectWriter
from pip_services4_commons.reflect import RecursiveObjectWriter, RecursiveObjectReader
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
class classAa():
param5 = "hello aa"
class classB(classA):
param4 = "inside 2"
my_classB = classB()
my_classC = classB()
# set_property
RecursiveObjectWriter.set_property(my_classB, "param2", "new value")
value1 = RecursiveObjectReader.get_property(my_classB, "param2")
print("The new values for the my_classB object are:", value1)
# set_properties
myMap = { 'param1': 789456, 'param2': "ABCaccc" }
RecursiveObjectWriter.set_properties(my_classB, myMap)
value2 = RecursiveObjectReader.get_properties(my_classB)
print("The new values for the my_classB object are:",value2)
# copy_proerties
value3 = RecursiveObjectReader.get_properties(my_classC)
print("The properties of my_classC and their values are:",value3)
RecursiveObjectWriter.copy_properties(my_classC, my_classB)
value4 = RecursiveObjectReader.get_properties(my_classC)
print("The new properties of my_classC and their values are:", value4)
After running, this code produces the following output:
![figure 7](figure7.png)
g) TypeDescriptor
This class stores a reference to a type represented by the type name and library (module) where the type is defined. This class has three methods. The equals method compares a descriptor to a value. The get_library method gets the library or module of a descriptor. The get_name method obtains the name of the object type. The to_string method returns a string representation of the descriptor with the format name[,library]. And, the static method from_string transforms a string into a Descriptor object. Below are some examples of these methods' usage.
import { TypeDescriptor } from "pip-services4-commons-node";
export class ClassAa {
public param5: string = "hello aa";
}
export class ClassA extends ClassAa {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export class ClassB extends ClassA {
public param4: string = "inside 2";
}
export function main(){
// Create type descriptors
let type1 = new TypeDescriptor("ClassA", "library1");
let type2 = new TypeDescriptor("ClassB", "library1");
// equals
let result1 = type1.equals(type2);
console.log("type1 equals type2:", result1);
// get_library
let library1 = type1.getLibrary();
console.log("The library of type1:", library1);
// get_name
let name1 = type1.getName();
console.log("The name of type1 is:", name1);
// from_string
let typeDescriptor = TypeDescriptor.fromString("classA,library1");
console.log("Type descriptor:", typeDescriptor);
}
/// TypeDescriptor
package main
import (
"fmt"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
ObjectAa
Param1 string
Param2 int
}
type ObjectAa struct {
Param5 string
}
func (c *ObjectA) MethodA() int {
return 123
}
type ObjectB struct {
*ObjectA
Param4 string
}
func NewObjectB() *ObjectB {
return &ObjectB{
ObjectA: NewObjectA(),
Param4: "inside 2",
}
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
ObjectAa: ObjectAa{
Param5: "hello aa",
},
}
}
func main() {
// Create type descriptors
type1 := creflect.NewTypeDescriptor("ObjectA", "library1")
type2 := creflect.NewTypeDescriptor("ObjectB", "library1")
// equals
result1 := type1.Equals(type2)
fmt.Println("type1 equals type2:", result1)
// get_library
library1 := type1.Package()
fmt.Println("The library of type1:", library1)
// get_name
name1 := type1.Name()
fmt.Println("The name of type1 is:", name1)
// from_string
typeDescriptor, _ := creflect.ParseTypeDescriptorFromString("ObjectA,library1")
fmt.Println("Type descriptor:", typeDescriptor)
}
# TypeDescriptor
from pip_services4_commons.reflect import TypeDescriptor
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
class classAa():
param5 = "hello aa"
class classB(classA):
param4 = "inside 2"
# Create type descriptors
type1 = TypeDescriptor("classA", "library1")
type2 = TypeDescriptor("classB", "library1")
# equals
result1 = type1.equals(type2)
print("type1 equals type2:", result1)
# get_library
library1 = type1.get_library()
print("The library of type1:", library1)
# get_name
name1 = type1.get_name()
print("The name of type1 is:", name1)
# from_string
type_descriptor = TypeDescriptor.from_string("classA,library1")
print("Type descriptor:", type_descriptor)
The output from this code is:
![figure 8](figure8.png)
h) TypeMatcher
This class allows us to match values based on equality. The match_type method matches an expected value to an actual one. The match_type_by_name method matches an expected type to an actual type. The match_value_type and match_value_type_by_name methods match an expected type to a type of value. The following code shows examples of their usage.
import { TypeCode, TypeMatcher } from "pip-services4-commons-node";
export class ClassA {
public param1: string = "hello";
public param2: number = 123;
public methodA(): number {
return 123;
}
}
export function main(){
let objectA1 = new ClassA();
// expected type: Object, actual type: classA, actualvalue: objectA1
let type1 = TypeMatcher.matchType("Object", TypeCode.Object, objectA1);
console.log("classA is an object:", type1);
// expected type: Object, actual type: String
let type2 = TypeMatcher.matchTypeByName("Object", TypeCode.String);
console.log("String is an object:", type2);
// expected type: classA, expected value: objectA1
let type3 = TypeMatcher.matchValueType(typeof(objectA1), objectA1);
console.log("objectA1 is of type classA:", type3);
// expected type: Object, actual value: objectA1
let type4 = TypeMatcher.matchValueTypeByName("Object", objectA1);
console.log("ObjectA1 is of type Object:", type4);
let string1 = "Hello World";
let type5 = TypeMatcher.matchValueTypeByName("String", string1);
console.log("string1 is of type String:", type5);
}
// TypeMatcher
package main
import (
"fmt"
refl "reflect"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
Param1 string
Param2 int
}
func (c *ObjectA) MethodA() int {
return 123
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
}
}
func main() {
objectA1 := NewObjectA()
// expected type: Object, actual type: objectA1, actualvalue: objectA1
type1 := creflect.TypeMatcher.MatchType("Object", refl.TypeOf(objectA1))
fmt.Println("objectA1 is an object:", type1)
// expected type: Object, actual type: String
type2 := creflect.TypeMatcher.MatchTypeByName("Object", refl.TypeOf("string"))
fmt.Println("String is an object:", type2)
// expected type: objectA1, expected value: objectA1
type3 := creflect.TypeMatcher.MatchValue(refl.TypeOf(objectA1), objectA1)
fmt.Println("objectA1 is of type objectA1:", type3)
// expected type: Object, actual value: objectA1
type4 := creflect.TypeMatcher.MatchValueByName("Object", objectA1)
fmt.Println("ObjectA1 is of type Object:", type4)
string1 := "Hello World"
type5 := creflect.TypeMatcher.MatchValueByName("String", string1)
fmt.Println("string1 is of type String:", type5)
}
# TypeMatcher
from pip_services4_commons.reflect import TypeMatcher
class classA:
param1 = "hello"
param2 = 123
def methodA():
param3 = "hello a"
return 123
objectA1 = classA()
# expected type: Object, actual type: classA, actualvalue: objectA1
type1 = TypeMatcher.match_type("Object",classA, objectA1)
print("classA is an object:", type1)
# expected type: Object, actual type: String
type2 = TypeMatcher.match_type_by_name("Object", "String")
print("String is an object:", type2)
# expected type: classA, expected value: objectA1
type3 = TypeMatcher.match_value_type(classA, objectA1)
print("objectA1 is of type classA:", type3)
# expected type: Object, actual value: objectA1
type4 = TypeMatcher.match_value_type_by_name("Object", objectA1)
print("ObjectA1 is of type Object:", type4)
string1 = "Hello World"
type5 = TypeMatcher.match_value_type_by_name("String", string1)
print("string1 is of type String:", type5)
After running this code, we will obtain the following results:
![figure 9](figure9.png)
i) TypeReflector
This class is used to examine the type of an object and create instances based on its type. Its create_instance_by_type method provides a way to create an instance of an object based on a type. The create_instance_by_descriptor method is similar to the previous one but uses a descriptor as input. The example below shows how to create an object of classA and verify that the values of its parameters are the ones defined in the class.
import { TypeReflector } from "pip-services4-commons-node";
export class ClassA {
public param1: string = "hello";
public param2: number = 123;
}
export function main(){
let myClassA = TypeReflector.createInstanceByType(ClassA);
console.log("The values of param1 and param2 are", myClassA.param1, "and", myClassA.param2);
}
// TypeReflector
package main
import (
"fmt"
refl "reflect"
creflect "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/reflect"
)
// Object
type ObjectA struct {
Param1 string
Param2 int
}
func NewObjectA() *ObjectA {
return &ObjectA{
Param1: "hello",
Param2: 123,
}
}
func main() {
myObjectA, _ := creflect.TypeReflector.CreateInstanceByType(refl.TypeOf(ObjectA{})) // Constructors with arguments are not supported
myObjectA.(*ObjectA).Param1 = "hello"
myObjectA.(*ObjectA).Param2 = 123
fmt.Println("The values of param1 and param2 are", myObjectA.(*ObjectA).Param1, "and", myObjectA.(*ObjectA).Param2)
}
# TypeReflector
from pip_services4_commons.reflect import TypeReflector, TypeDescriptor
class classA:
param1 = "hello"
param2 = 123
my_classA = TypeReflector.create_instance_by_type(classA)
print("The values of param1 and param2 are",my_classA.param1, "and", my_classA.param2)
After running it, we get:
![figure 10](figure10.png)
Wrapping up
In this tutorial, we have learned what reflection is and how to use the Reflect library available in the PIP.Services toolkit, which provides several tools for class introspection. We have seen all its classes and examples of their main methods' usage.