Reflection

How to create components that can introspect.

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-services3-commons-nodex";

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);
}

using PipServices3.Commons.Reflect;

using System;

namespace ExampleApp
{   
    public class ClassA
    {
        public int MethodA()
        {
            return 123;
        }

        public void MethodB()
        {
            Console.WriteLine("hello world b");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = new ClassA();
            // Obtain all methods in classA

            var methods1 = MethodReflector.GetMethodNames(myClassA);

            string methodsStr = "";
            methods1.ForEach(x => methodsStr += x + ", ");

            Console.WriteLine($"The methods in myClassA are: {methodsStr}");

            // Ask whether a specific method exists or not
            var methods2 = MethodReflector.HasMethod(myClassA, "MethodA");
            Console.WriteLine($"MethodA belongs to myClassA: {methods2}");

            var methods3 = MethodReflector.HasMethod(myClassA, "methodC");
            Console.WriteLine($"methodC belongs to myClassA: {methods3}");

            // Invoke a method in classA
            var methods4 = MethodReflector.InvokeMethod(myClassA, "MethodA");
            Console.WriteLine($"After running MethodA the result is: {methods4}");
        }
    }
}

// Method Reflector

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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)

}


import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA = ClassA();
  // Obtain all methods in classA

  var methods1 = MethodReflector.getMethodNames(myClassA);
  print('The methods in myClassA are: $methods1');

  // Ask whether a specific method exists or not
  var methods2 = MethodReflector.hasMethod(myClassA, 'methodA');
  print('methodA belongs to myClassA: $methods2');

  var methods3 = MethodReflector.hasMethod(myClassA, 'methodC');
  print('methodC belongs to myClassA: $methods3');

  // Invoke a method in classA
  var methods4 = MethodReflector.invokeMethod(myClassA, 'methodA', []);
  print('After running methodA the result is: $methods4');
}

class ClassA {
  int methodA() {
    return 123;
  }

  void methodB() {
    print('hello world b');
  }
}


# Method Reflector

from pip_services3_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)

Not available

After running the above code, we will get the following output:

figure 1

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-services3-commons-nodex";

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);
}

using PipServices3.Commons.Reflect;

using System;

namespace ExampleApp
{   
    public class ClassA
    {
        public string  param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = new ClassA();
            // Obtain all properties in ClassA

            var properties = ObjectReader.GetPropertyNames(myClassA);
            
            string propertiesStr = "";
            properties.ForEach(x => propertiesStr += x + ", ");

            Console.WriteLine($"The properties in myClassA are: {propertiesStr}");
            

            // Obtain the value of a property in classA
            var value1 = ObjectReader.GetProperty(myClassA, "param1");
            Console.WriteLine($"The value of param1 is: {value1}");

            var value2 = ObjectReader.GetProperties(myClassA);

            propertiesStr = "";
            foreach (var prop in value2)
                propertiesStr += $"{prop.Key}:{prop.Value}, ";

            Console.WriteLine($"The properties and values in myClassA are: {{{propertiesStr}}}");
        }
    }
}

// Object reader

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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)
}

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA = ClassA();
  // Obtain all properties in ClassA

  var properties = ObjectReader.getPropertyNames(myClassA);
  print('The properties in myClassA are: $properties');

  // Obtain the value of a property in classA
  var value1 = ObjectReader.getProperty(myClassA, 'param1');
  print('The value of param1 is: $value1');

  var value2 = ObjectReader.getProperties(myClassA);
  print('The properties and values in myClassA are: $value2');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

# Object reader
from pip_services3_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)


Not available

Once the code above is executed, we will get the following result:

figure 2

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);
} 
using PipServices3.Commons.Reflect;

using System;
using System.Collections.Generic;

namespace ExampleApp
{

    class Program
    {
        static void Main(string[] args)
        {
            // Obtain properties from a map(dictionary)
            var myMap = new Dictionary<string, dynamic>() { { "key1", 123 }, { "key2", "ABC" } };

            var hasProperty1 = ObjectReader.HasProperty(myMap, "key1");
            var value1 = ObjectReader.GetProperty(myMap, "key1");
            Console.WriteLine($"MyMap contains key1: {hasProperty1}");
            Console.WriteLine($"The value of key1 is : {value1}");

            // Obtain properties from an array
            var myArray = new List<int>() { 1, 2, 3 };
            var hasProperty2 = ObjectReader.HasProperty(myArray, "5");
            var hasProperty3 = ObjectReader.HasProperty(myArray, "0");
            var value2 = ObjectReader.GetProperty(myArray, "0");

            Console.WriteLine($"myArray contains an element with index 5: {hasProperty2}");
            Console.WriteLine($"myArray contains an element with index 0: {hasProperty3}");
            Console.WriteLine($"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)
import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  // Obtain properties from a map(dictionary)
  var myMap = {'key1': 123, 'key2': 'ABC'};

  var hasProperty1 = ObjectReader.hasProperty(myMap, 'key1');
  var value1 = ObjectReader.getProperty(myMap, 'key1');
  print('MyMap contains key1: $hasProperty1');
  print('The value of key1 is : $value1');

  // Obtain properties from an array
  var myArray = [1, 2, 3];
  var hasProperty2 = ObjectReader.hasProperty(myArray, '5');
  var hasProperty3 = ObjectReader.hasProperty(myArray, '0');
  var value2 = ObjectReader.getProperty(myArray, '0');

  print('myArray contains an element with index 5: $hasProperty2');
  print('myArray contains an element with index 0: $hasProperty3');
  print('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)
Not available

figure 3

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-services3-commons-nodex";

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);
}
using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{
    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = new ClassA();

            var value1 = ObjectReader.GetProperty(myClassA, "param1");
            Console.WriteLine($"The value of param1 is: {value1}");

            ObjectWriter.SetProperty(myClassA, "param1", "hello 2");
            var value2 = ObjectReader.GetProperty(myClassA, "param1");
            Console.WriteLine($"The new value of param1 is: {value2}");

            var myMap = new Dictionary<string, dynamic>() { { "param1", 123 }, { "param2", "ABC" } };
            ObjectWriter.SetProperties(myClassA, myMap);
            var value3 = ObjectReader.GetProperties(myClassA);
            Console.WriteLine($"The new parameter values are: {ObjectToString(value3)}");

            // Map(dictionary)
            myMap = new Dictionary<string, dynamic>() { { "key1", 123 }, { "key2", "ABC" } };
            ObjectWriter.SetProperties(myMap, new Dictionary<string, dynamic>() { { "key1", 15422 }, { "key2", "ab" } });
            var value4 = ObjectReader.GetProperties(myMap);
            Console.WriteLine($"The new values in the map are : {ObjectToString(value4)}");


            myMap = new Dictionary<string, dynamic>() { { "key1", 123 }, { "key2", "ABC" } };
            ObjectWriter.SetProperty(myMap, "key1", "XYZ");
            value2 = ObjectReader.GetProperty(myMap, "key1");
            Console.WriteLine($"The new value in the map is : {value2}");

            // Array
            var myArray = new List<object> { 1, 2, 3 };
            ObjectWriter.SetProperty(myArray, "0", 123);
            var value5 = ObjectReader.GetProperty(myArray, "0");
            Console.WriteLine($"The new value in the array is : {value5}");
        }

        static string ObjectToString(object obj)
        {
            string objStr = "";

            if (obj is IDictionary)
                foreach (var prop in (obj as Dictionary<string, dynamic>))
                    objStr += $"{prop.Key}:{prop.Value}, ";

            else if (obj is IList)
                (obj as List<string>).ForEach(x => objStr += x + ", ");

            return objStr[0..^2];
        }
    }
}

// Object writer - Setting property values

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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)
}

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA = ClassA();

  var value1 = ObjectReader.getProperty(myClassA, 'param1');
  print('The value of param1 is: $value1');

  ObjectWriter.setProperty(myClassA, 'param1', 'hello 2');
  var value2 = ObjectReader.getProperty(myClassA, 'param1');
  print('The new value of param1 is: $value2');

  var myMap1 = {'param1': 123, 'param2': 'ABC'};
  ObjectWriter.setProperties(myClassA, myMap1);
  var value3 = ObjectReader.getProperties(myClassA);
  print('The new parameter values are: $value3');

  // Map(dictionary)
  var myMap2 = {'key1': 123, 'key2': 'ABC'};
  ObjectWriter.setProperties(myMap2, {'key1': 15422, 'key2': 'ab'});
  var value4 = ObjectReader.getProperties(myMap2);
  print('The new values in the map are : $value4');

  var myMap3 = {'key1': 123, 'key2': 'ABC'};
  ObjectWriter.setProperty(myMap3, 'key1', 'XYZ');
  value2 = ObjectReader.getProperty(myMap3, 'key1');
  print('The new value in the map is : $value2');

  // Array
  var myArray = [1, 2, 3];
  ObjectWriter.setProperty(myArray, '0', 123);
  var value5 = ObjectReader.getProperty(myArray, '0');
  print('The new value in the array is : $value5');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

# Object writer - Setting property values

from pip_services3_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)
Not available

After running the above code, we will get the following result:

figure 4

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.

// Property reflector

import { PropertyReflector } from "pip-services3-commons-nodex";

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

using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{
    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = new ClassA();

    // Obtain all property names
            var properties = PropertyReflector.GetPropertyNames(myClassA);
            Console.WriteLine($"The properties of myClassA are: {ObjectToString(properties)}");

            // Find out whether an object has a property or not
            var hasParam1 = PropertyReflector.HasProperty(myClassA, "param1");
            Console.WriteLine($"ClassA contains param1: {hasParam1}");

            // Obtain all property names and their values
            var value3 = PropertyReflector.GetProperties(myClassA);
            Console.WriteLine($"The properties of myClassA are: {ObjectToString(value3)}");

            // Change the value of a parameter
            var value1 = PropertyReflector.GetProperty(myClassA, "param2");
            PropertyReflector.SetProperty(myClassA, "param2", 14785);
            var value2 = PropertyReflector.GetProperty(myClassA, "param2");
            Console.WriteLine($"The value of param2 is: {value1}");
            Console.WriteLine($"The new value of param2 is: {value2}");
        }

        static string ObjectToString(object obj)
        {
            string objStr = "";

            if (obj is IDictionary)
                foreach (var prop in (obj as Dictionary<string, dynamic>))
                    objStr += $"{prop.Key}:{prop.Value}, ";

            else if (obj is IList)
                (obj as List<string>).ForEach(x => objStr += x + ", ");

            return objStr[0..^2];
        }
    }
}

// Property reflector

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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)

}

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA = ClassA();

  // Obtain all property names
  var properties = PropertyReflector.getPropertyNames(myClassA);
  print('The properties of myClassA are: $properties');

  // Find out whether an object has a property or not
  var has_param1 = PropertyReflector.hasProperty(myClassA, 'param1');
  print('ClassA contains param1: $has_param1');

  // Obtain all property names and their values
  var value3 = PropertyReflector.getProperties(myClassA);
  print('The properties of myClassA are: $value3');

  // Change the value of a parameter
  var value1 = PropertyReflector.getProperty(myClassA, 'param2');
  PropertyReflector.setProperty(myClassA, 'param2', 14785);
  var value2 = PropertyReflector.getProperty(myClassA, 'param2');
  print('The value of param2 is: $value1');
  print('The new value of param2 is: $value2');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

# Property reflector

from pip_services3_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)
Not available

After running the above code, we will get the following results.

figure 5

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.

// Property reflector

import { RecursiveObjectReader } from "pip-services3-commons-nodex";


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)
}
// Property reflector

using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{
    public class ClassAa
    {
        public string param5 = "hello aa";

    }

    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class ClassB : ClassA
    {
        public string param4 = "inside 2";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = new ClassA();
            var myClassB = new ClassB();

            var value1 = RecursiveObjectReader.GetPropertyNames(myClassA);
            Console.WriteLine($"The property names of myClassA are: {ObjectToString(value1)}");

            var value2 = RecursiveObjectReader.HasProperty(myClassB, "param5");
            Console.WriteLine($"myClassB contains param5: {value2}");

            var value3 = RecursiveObjectReader.GetProperties(myClassB);
            Console.WriteLine($"The properties of myClassB are: {ObjectToString(value3)}");

            var value4 = RecursiveObjectReader.GetProperty(myClassB, "param4");
            Console.WriteLine($"The value of param4 is: {value4}");
        }

        static string ObjectToString(object obj)
        {
            string objStr = "";

            if (obj is IDictionary)
                foreach (var prop in (obj as Dictionary<string, dynamic>))
                    objStr += $"{prop.Key}:{prop.Value}, ";

            else if (obj is IList)
                (obj as List<string>).ForEach(x => objStr += x + ", ");

            return objStr[0..^2];
        }
    }
}

// Property reflector

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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)
}
// Property reflector

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA = ClassA();
  var myClassB = ClassB();

  var value1 = RecursiveObjectReader.getPropertyNames(myClassA);
  print('The property names of myClassA are: $value1');

  var value2 = RecursiveObjectReader.hasProperty(myClassB, 'param5');
  print('myClassB contains param5: $value2');

  var value3 = RecursiveObjectReader.getProperties(myClassB);
  print('The properties of myClassB are: $value3');

  var value4 = RecursiveObjectReader.getProperty(myClassB, 'param4');
  print('The value of param4 is: $value4');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

class ClassAa {
  String param5 = 'hello aa';
}

class ClassB extends ClassA {
  String param4 = 'inside 2';
}

# RecursiveObjectReader

from pip_services3_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)

Not available
figure 6

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:

// RecursiveObjectWriter

import { RecursiveObjectReader, RecursiveObjectWriter } from "pip-services3-commons-nodex";


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

using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{
    public class ClassAa
    {
        public string param5 = "hello aa";

    }

    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class ClassB : ClassA
    {
        public string param4 = "inside 2";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassB = new ClassB();
            var myClassC = new ClassB();

            // set_property
            RecursiveObjectWriter.SetProperty(myClassB, "param2", "new value");
            var value1 = RecursiveObjectReader.GetProperty(myClassB, "param2");
            Console.WriteLine($"The new values for the myClassB object are: {value1}");

            // set_properties
            var myMap = new Dictionary<string, dynamic> { { "param1", 789456 }, { "param2", "ABCaccc" } };
            RecursiveObjectWriter.SetProperties(myClassB, myMap);
            var value2 = RecursiveObjectReader.GetProperties(myClassB);
            Console.WriteLine($"The new values for the myClassB object are: {ObjectToString(value2)}");

            // copy_proerties
            var value3 = RecursiveObjectReader.GetProperties(myClassC);
            Console.WriteLine($"The properties of myClassC and their values are: {ObjectToString(value3)}");
            RecursiveObjectWriter.CopyProperties(myClassC, myClassB);
            var value4 = RecursiveObjectReader.GetProperties(myClassC);
            Console.WriteLine($"The new properties of myClassC and their values are: {ObjectToString(value4)}");
        }

        static string ObjectToString(object obj)
        {
            string objStr = "";

            if (obj is IDictionary)
                foreach (var prop in (obj as Dictionary<string, dynamic>))
                    objStr += $"{prop.Key}:{prop.Value}, ";

            else if (obj is IList)
                (obj as List<string>).ForEach(x => objStr += x + ", ");

            return objStr[0..^2];
        }
    }
}

// RecursiveObjectWriter

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassB = ClassB();
  var myClassC = ClassB();

  // set_property
  RecursiveObjectWriter.setProperty(myClassB, 'param2', 'new value');
  var value1 = RecursiveObjectReader.getProperty(myClassB, 'param2');
  print('The new values for the myClassB object are: $value1');

  // set_properties
  var myMap = {'param1': 789456, 'param2': 'ABCaccc'};
  RecursiveObjectWriter.setProperties(myClassB, myMap);
  var value2 = RecursiveObjectReader.getProperties(myClassB);
  print('The new values for the myClassB object are: $value2');

  // copy_proerties
  var value3 = RecursiveObjectReader.getProperties(myClassC);
  print('The properties of myClassC and their values are: $value3');
  RecursiveObjectWriter.copyProperties(myClassC, myClassB);
  var value4 = RecursiveObjectReader.getProperties(myClassC);
  print('The new properties of myClassC and their values are: $value4');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

class ClassAa {
  String param5 = 'hello aa';
}

class ClassB extends ClassA {
  String param4 = 'inside 2';
}

# RecursiveObjectWriter

from pip_services3_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)

Not available

After running, this code produces the following output:

figure 7

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.

// TypeDescriptor

import { TypeDescriptor } from "pip-services3-commons-nodex";


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

using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{
    public class ClassAa
    {
        public string param5 = "hello aa";
    }

    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class ClassB : ClassA
    {
        public string param4 = "inside 2";
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Create type descriptors
            var type1 = new TypeDescriptor("ClassA", "library1");
            var type2 = new TypeDescriptor("ClassB", "library1");

            // equals
            var result1 = type1.Equals(type2);
            Console.WriteLine($"type1 equals type2: {result1}");

            // get_library
            var library1 = type1.Library;
            Console.WriteLine($"The library of type1: {library1}");

            // get_name
            var name1 = type1.Name;
            Console.WriteLine($"The name of type1 is: {name1}");

            // from_string
            var typeDescriptor = TypeDescriptor.FromString("classA,library1");
            Console.WriteLine($"Type descriptor: {typeDescriptor}");
        }
    }
}

// TypeDescriptor

package main

import (
	"fmt"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  // Create type descriptors
  var type1 = TypeDescriptor('ClassA', 'library1');
  var type2 = TypeDescriptor('ClassB', 'library1');

  // equals
  var result1 = type1.equals(type2);
  print('type1 equals type2: $result1');

  // get_library
  var library1 = type1.getLibrary();
  print('The library of type1: $library1');

  // get_name
  var name1 = type1.getName();
  print('The name of type1 is: $name1');

  // from_string
  var typeDescriptor = TypeDescriptor.fromString('classA,library1');
  print('Type descriptor: $typeDescriptor');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

class ClassAa {
  String param5 = 'hello aa';
}

class ClassB extends ClassA {
  String param4 = 'inside 2';
}

# TypeDescriptor
from pip_services3_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)

Not available

The output from this code is:

figure 8

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.

// TypeMatcher

import { TypeCode, TypeDescriptor, TypeMatcher } from "pip-services3-commons-nodex";

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);
}
using PipServices3.Commons.Reflect;

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleApp
{

    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;

        public int MethodA()
        {
            return 123;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var objectA1 = new ClassA();

            // expected type: Object, actual type: ClassA, actualvalue: objectA1
            var type1 = TypeMatcher.MatchType("Object", objectA1.GetType(), objectA1);
            Console.WriteLine($"ClassA is an object: {type1}");

            // expected type: Object, actual type: String
            var type2 = TypeMatcher.MatchTypeByName("Object", typeof(string));
            Console.WriteLine($"String is an object: {type2}");

            // expected type: ClassA, expected value: objectA1
            var type3 = TypeMatcher.MatchType(objectA1.GetType(), objectA1.GetType());
            Console.WriteLine($"objectA1 is of type ClassA: {type3}");

            // expected type: Object, actual value: objectA1
            var type4 = TypeMatcher.MatchTypeByName("Object", objectA1.GetType());
            Console.WriteLine($"ObjectA1 is of type Object: {type4}");

            var string1 = "Hello World";
            var type5 = TypeMatcher.MatchTypeByName("String", string1.GetType());
            Console.WriteLine($"string1 is of type String: {type5}");
        }
    }
}

// TypeDescriptor

package main

import (
	"fmt"
	refl "reflect"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var objectA1 = ClassA();

  // expected type: Object, actual type: classA, actualvalue: objectA1
  var type1 = TypeMatcher.matchType('Object', TypeCode.Object, objectA1);
  print('classA is an object: $type1');

  // expected type: Object, actual type: String
  var type2 = TypeMatcher.matchTypeByName('Object', TypeCode.String);
  print('String is an object: $type2');

  // expected type: classA, expected value: objectA1
  var type3 = TypeMatcher.matchValueType(TypeCode.Object, objectA1);
  print('objectA1 is of type classA: $type3');

  // expected type: Object, actual value: objectA1
  var type4 = TypeMatcher.matchValueTypeByName('Object', objectA1);
  print('ObjectA1 is of type Object: $type4');

  var string1 = 'Hello World';
  var type5 = TypeMatcher.matchValueTypeByName('String', string1);
  print('string1 is of type String: $type5');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

# TypeMatcher
from pip_services3_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)


Not available

After running this code, we will obtain the following results:

figure 9

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.

// TypeReflector

import { TypeReflector } from "pip-services3-commons-nodex";

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

using PipServices3.Commons.Reflect;

using System;

namespace ExampleApp
{

    public class ClassA
    {
        public string param1 = "hello";
        public int param2 = 123;
    }

    class Program
    {
        static void Main(string[] args)
        {
            var myClassA = TypeReflector.CreateInstanceByType(typeof(ClassA));
            Console.WriteLine($"The values of param1 and param2 are {(myClassA as ClassA).param1} and {(myClassA as ClassA).param2}");
        }
    }
}

// TypeDescriptor

package main

import (
	"fmt"
	refl "reflect"

	creflect "github.com/pip-services3-gox/pip-services3-commons-gox/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

import 'package:pip_services3_commons/pip_services3_commons.dart';

void main(List<String> arguments) async {
  var myClassA =
      TypeReflector.createInstanceByType(ClassA().runtimeType, []) as ClassA;
  print(
      'The values of param1 and param2 are ${myClassA.param1} and ${myClassA.param2}');
}

class ClassA {
  String param1 = 'hello';
  int param2 = 123;

  int methodA() {
    return 123;
  }
}

# TypeReflector
from pip_services3_commons.reflect import TypeReflector, TypeDescriptor
import pip_services3_commons.config 

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)

Not available

After running it, we get:

figure 10

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.