BestProg

Search
Skip to content
  • Site map
  • Video
  • Patterns
  • Java
  • C#
  • C++
  • Pascal / Delphi
  • Databases
  • Python
  • Kotlin
  • JavaScript
  • Українська
  • English
  • Русский
C#, Theory

C#. .NET. Metadata of types. Purpose and features of use

May 18, 2021 BestProgISch

Metadata of types. Purpose and features of use. The need for metadata. Ways to get type information


Contents

  • 1. What is type metadata? An example demonstrating the need to use type metadata
  • 2. Types described by metadata
  • 3. Ways to get type information
  • 4. Getting information about the type using the System.Object.GetType() method. Example
  • 5. Getting information about a type using the typeof() operator. Example
  • 6. Retrieving type information using the System.Type.GetType() method. Example
  • Related topics

Search other websites:




1. What is type metadata? An example demonstrating the need to use type metadata

After a program is written in C#, it is compiled. The compilation creates an assembly that is the base unit of .NET. An assembly means a file with the *.dll or *.exe extension. Each assembly you create has parts. One of the components of the assembly is the so-called metadata, with the help of which the types that have been defined in the program are described. For example, if the program implements a class named MyClass, then it is considered that this type is MyClass, and this type is described by metadata in the compiled assembly.

Metadata types are widely used in communication between programs. The following uses of type metadata can be listed:

  • serialization of objects;
  • distributed applications;
  • remote work;
  • XML services;
  • interlanguage interaction in the IDE;
  • other uses.

Figure 1 shows an example of the use of metadata in the case of distributed applications. The case of combining computers into a local network and their interaction is considered. Let the server host mathematical software that contains the corresponding functionality. From one or more client computers, a request is made to the server to carry out calculations, for example, solving a quadratic equation. The server receives the request, performs the calculations, and returns the result to the client.

In order for the client and server to interact with each other, a common assembly is required. In our case, this is the assembly ClassLibrary1.dll. The assembly contains information about the CalcEquation() method for calculating a quadratic equation. The client and server use the assembly metadata to obtain information about the content of the assembly (types, method names, method parameters, etc.). The assembly metadata is accessed using a reflection mechanism.

C# .NET. Communication between client and server using co-assembly metadata

Figure 1. Communication between client and server using co-assembly metadata

  ⇑

2. Types described by metadata

In C# .NET, the following types are described using metadata:

  • classes (class)
  • interfaces (interface)
  • structures (struct)
  • enumerations (enum)
  • delegates (delegate).

  ⇑

3. Ways to get type information

Type information can be obtained in the following ways:

  • using the ildasm.exe utility. The ildasm.exe utility uses reflection to access assembly items by reading type metadata. More details about the operation of the ildasm.exe utility are described here;
  • programmatically.

To get metadata programmatically, you can use one of three methods:

  • use the System.Object.GetType() method. This method allows you to define the metadata of an object;
  • use the typeof() operator. This method allows you to define type information without creating an object;
  • use the System.Type.GetType() method. This method allows you to determine information about a type based on its name (string representation) using metadata.

The first two methods to programmatically obtain metadata implement an early binding mechanism. With this kind of binding, the type information is known in the program at compile time.

The third method (using the System.Type.GetType() method) implements the late binding mechanism. In the case of late binding, the type information is unknown at compile time. The compiler contains generic type definition code based on what is called reflection. More details about the features of the use of reflection are described here.

  ⇑

4. Getting information about the type using the System.Object.GetType() method. Example

As you know, the base class for all classes in .NET is the class object or System.Object. To get metadata of types using the tools of the System.Object class, the GetType() method is used, which has the following general form:

public System.Type GetType();

In the simplest case, the System.Object.GetType() method is applied to an instance of the class according to the following pattern

MyClass mc = new MyClass();
Type tp = mc.GetType();

The result is a tp instance of type Type. This instance contains all the necessary information about the type MyClass.

Example. The example demonstrates the use of the reflection mechanism for the Complex class. The so-called early binding is implemented.

Let the Complex class be given, which has the following elements:

  • internal fields re, im;
  • constructors without parameters and with two parameters;
  • properties Re and Im for accessing the internal fields of the class;
  • methods Add(), Sub() that implement operations of addition and subtraction of complex numbers;
  • the Print() method displays information about the number.

 

using System;
using System.Reflection;

namespace ConsoleApp15
{
  // A class that implements operations on complex numbers
  class Complex
  {
    // Public fields
    private double re, im;

    // Constructors
    public Complex(double _re, double _im)
    {
      re = _re; im = _im;
    }

    public Complex() : this(0, 0) { }

    // Properties
    public double Re
    {
      get { return re; }
      set { re = value; }
    }

    public double Im
    {
      get { return im; }
      set { im = value; }
    }

    // Methods
    public Complex Add(double re2, double im2)
    {
      return new Complex(re + re2, im + im2);
    }

    public Complex Sub(double re2, double im2)
    {
      return new Complex(re - re2, im - im2);
    }

    public void Print(string text)
    {
      Console.Write(text);
      Console.Write("{0:f2}", re);
      if (im > 0)
        Console.Write("+");
      Console.WriteLine("{0:f2}*j", im);
    }
  }

  class Program
  {

    static void Main(string[] args)
    {
      // Get information about the types of the Complex class
      // using System.Object.GetType()

      // 1. Declare an instance of the Complex class
      Complex cm = new Complex(5, 8);

      // 2. Get the type from the instance
      Type tp = cm.GetType(); // method GetType() of class Object

      // 3. Get a list of methods of the Complex class
      // Select methods according to the following criteria:
      // - only public-methods;
      // - only from an instance;
      // - only those methods that are declared in the Complex class.
      MethodInfo[] mi = tp.GetMethods(
        BindingFlags.Public |
        BindingFlags.Instance |
        BindingFlags.DeclaredOnly
        );

      // 4. Display the names of the methods of the Complex class
      foreach (MethodInfo m in mi)
      {
        Console.WriteLine("{0}", m.Name);
      }

      Console.ReadKey();
    }
  }
}

The result of the program

get_Re
set_Re
get_Im
set_Im
Add
Sub
Print

As you can see from the result, not only the names of the methods are displayed, but also the names of the methods associated with the properties Re and Im of the class. To select separately the Add(), Sub(), Print() methods, you need to get a list of properties, then in a loop form a new set of methods without property names. This is another topic.

  ⇑

5. Getting information about a type using the typeof() operator. Example

You can get information about a type using the typeof() operator, which has the following general form:

typeof(SomeType)

where SomeType is some type.

In the simplest case, to determine information about the type of MyClass, using typeof() can be, for example, like this

class MyClass
{
  // ...
}

...

Type tp = typeof(MyClass);

The result is a tp instance of type System.Type that contains information about the MyClass class.

More details on using the typeof() operator are described here.

Example. On the example of the Complex class (see the previous example), a list of constructors of this class is obtained. Below is the abbreviated code for solving the task.

using System;
using System.Reflection;

...

// A class that implements operations on complex numbers
class Complex
{
  ...
}

...

static void Main(string[] args)
{
  // Get information about the types of the Complex class using typeof()

  // 1. Get an instance of System.Type from the Complex class
  Type tp = typeof(Complex);

  // 2. Get a list of the Complex class constructors
  ConstructorInfo[] ci = tp.GetConstructors();

  // 4. Print a list of constructors with parameters
  foreach (ConstructorInfo c in ci)
  {
    Console.Write(c.Name + "(");

    // Generate a list of constructor parameters
    ParameterInfo[] pi = c.GetParameters();

    for (int i = 0; i < pi.Length; i++)
    {
      Console.Write("{0} {1}",
      pi[i].ParameterType.Name, pi[i].Name);
      if (i < pi.Length - 1)
        Console.Write(", ");
    }
    Console.WriteLine(")");
  }
  Console.ReadKey();
}

...

The result of the program

.ctor(Double _re, Double _im)
.ctor()

  ⇑

6. Retrieving type information using the System.Type.GetType() method. Example

The GetType() method of the System.Type class allows you to get information about a type based on its name as a string of type System.String. This method of obtaining type information is used in the so-called late binding.

Late binding is a technique of creating and calling an instance of a certain type (for example, a class) during program execution without first connecting it at compile time. With late binding, the type name is obtained as a string. Then, based on this string, an instance of the System.Type is formed. More details about the specifics of the late binding implementation are described here.

The GetType() method has several overloaded implementations, one of which has the following general form

public static System.Type GetType(string typeName);

here

  • typeName – the name of the type to get information about. Note that the string is of type System.String.

Example. Suppose the program needs to get information about the Triangle type of another assembly MyConsoleApp. The type and assembly information is unknown at compile time. Only the assembly name (MyConsoleApp) and the type name (Triangle) are known.

The following snippet demonstrates how to use the System.Type.GetType() method to get information about the type of a Triangle. The fragment gets a list of attributes of the Triangle class.

using System;
using System.Reflection;

...

// 1. Load the assembly
Assembly asm = Assembly.Load("MyConsoleApp");

// 2. Get the type from assembly
Type tp = asm.GetType("MyConsoleApp.Triangle");

// 3. Get attributes of class MyClass2
object[] objs = tp.GetCustomAttributes(true);

// 4. Display attribute names on screen
foreach (object obj in objs)
{
  Console.WriteLine(obj.GetType().Name);
}

...

  ⇑


Related topics

  • Reflection of types. Getting type metadata. The System.Reflection namespace. Class System.Type. Ways to get information about types. Operator typeof
  • Examples of obtaining information about methods, interfaces, classes, structures, enumerations, delegates, type fields, method parameters, type statistics
  • Dynamically loadable assemblies. Class Assembly. Methods Load() and LoadFrom()
  • Late binding. Method call. Example. Class System.Activator. Method Invoke()
  • Examples of using the reflection based on late binding

  ⇑


 

 

C#late bindingmetadatatypetypeof

Post navigation

Previous PostC#. .NET. Examples of using the reflection based on late bindingNext PostPascal. Principles of structured programming. Modular software development

Programming: theory and practice

  • Site map
  • Patterns
  • Java
  • C++
  • C#
  • Pascal / Delphi
  • Databases
  • Python
  • Kotlin
  • JavaScript
  • C# (176)
    • Practice (46)
      • MS Visual Studio 2010 (34)
      • MS Visual Studio 2017 (7)
      • MS Visual Studio 2019 (13)
    • Theory (130)
      • ADO .NET (7)
  • C++ (163)
    • Practice (31)
      • Borland C++ Builder 2007 (16)
      • MS Visual Studio 2010 (18)
    • Theory (133)
      • Visual C++ (128)
  • Computer graphics (3)
  • Databases (48)
    • SQL (4)
  • Java (108)
    • Practice (6)
    • Theory (102)
  • JavaScript (22)
    • Practice (1)
    • Theory (21)
  • Kotlin (22)
    • Practice (1)
    • Theory (21)
  • Mathematical software (9)
  • Pascal/Delphi (40)
    • Practice (19)
      • Delphi-7 (4)
      • Embarcadero RAD Studio 2010 (17)
    • Theory (22)
  • Patterns (20)
  • Python (96)
    • Practice (4)
    • Theory (92)
  • Term Papers (6)
  • C++. STL. Algorithms. Algorithms for exchanging values of sequence elementsMarch 21, 2023
  • C++. STL. Algorithms. Algorithms that change all elements of a sequenceMarch 20, 2023
  • C++. STL. Algorithms for working with setsMarch 15, 2023
  • C++. STL. Non-modifying algorithmsMarch 4, 2023
  • C++. STL. Algorithms that do not change the values and order of elementsFebruary 24, 2023
  • C++. STL. Permutation algorithmsFebruary 19, 2023
  • C++. STL. Algorithms for determining the minimum and maximum. ExampleFebruary 15, 2023
  • C++. STL. Algorithms for working with data, which are presented according to the “heap” principleFebruary 15, 2023
  • C++. Conditional compilation. Directives #if, #else, #elif, #endif, #ifdef, #ifndef. The defined operatorFebruary 10, 2023
  • C++. Preprocessor. General information. Preprocessor directives. ReviewFebruary 6, 2023

Privacy policy

When using the site materials reference to the site is required.

Proudly powered by WordPress