🎓 A1Learner
🔍
0 of 28 lessons completed

C# Project: Type Inspector

The Type Inspector project combines a custom attribute with reflection to report on marked classes. It prints each class name, its author, and its declared method count in sorted order.

The marked classes

Three small classes each carry an Info attribute with a different author. Each class declares two methods.

using System;

[AttributeUsage(AttributeTargets.Class)]
class InfoAttribute : Attribute
{
    public string Author { get; }
    public InfoAttribute(string author)
    {
        Author = author;
    }
}

[Info("Hana")]
class Sensor
{
    public string Start() { return "Sensor started"; }
    public string Stop() { return "Sensor stopped"; }
}

[Info("Omar")]
class Valve
{
    public string Open() { return "Valve opened"; }
    public string Close() { return "Valve closed"; }
}

[Info("Priya")]
class Motor
{
    public string Spin() { return "Motor spinning"; }
    public string Halt() { return "Motor halted"; }
}

class Program
{
    static void Main(string[] args)
    {
        Sensor sensor = new Sensor();
        Valve valve = new Valve();
        Motor motor = new Motor();
        Console.WriteLine(sensor.Start());
        Console.WriteLine(valve.Open());
        Console.WriteLine(motor.Spin());
    }
}

Inspect one type

The inspector reads the author from the attribute on Sensor. It also counts the methods Sensor declares itself.

using System;
using System.Reflection;

[AttributeUsage(AttributeTargets.Class)]
class InfoAttribute : Attribute
{
    public string Author { get; }
    public InfoAttribute(string author)
    {
        Author = author;
    }
}

[Info("Hana")]
class Sensor
{
    public string Start() { return "Sensor started"; }
    public string Stop() { return "Sensor stopped"; }
}

[Info("Omar")]
class Valve
{
    public string Open() { return "Valve opened"; }
    public string Close() { return "Valve closed"; }
}

[Info("Priya")]
class Motor
{
    public string Spin() { return "Motor spinning"; }
    public string Halt() { return "Motor halted"; }
}

class Program
{
    static void Main(string[] args)
    {
        Type type = typeof(Sensor);
        InfoAttribute info = type.GetCustomAttribute<InfoAttribute>();
        int count = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Length;
        Console.WriteLine(type.Name + " by " + info.Author + ": " + count + " methods");
    }
}

Sort the type names

The inspector collects the name of each type into a list. Sorting the list puts the names in alphabetical order.

using System;
using System.Collections.Generic;

[AttributeUsage(AttributeTargets.Class)]
class InfoAttribute : Attribute
{
    public string Author { get; }
    public InfoAttribute(string author)
    {
        Author = author;
    }
}

[Info("Hana")]
class Sensor
{
    public string Start() { return "Sensor started"; }
    public string Stop() { return "Sensor stopped"; }
}

[Info("Omar")]
class Valve
{
    public string Open() { return "Valve opened"; }
    public string Close() { return "Valve closed"; }
}

[Info("Priya")]
class Motor
{
    public string Spin() { return "Motor spinning"; }
    public string Halt() { return "Motor halted"; }
}

class Program
{
    static void Main(string[] args)
    {
        Type[] types = { typeof(Sensor), typeof(Valve), typeof(Motor) };
        List<string> names = new List<string>();
        foreach (Type type in types)
        {
            names.Add(type.Name);
        }
        names.Sort();
        foreach (string name in names)
        {
            Console.WriteLine(name);
        }
    }
}

Example

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

[AttributeUsage(AttributeTargets.Class)]
class InfoAttribute : Attribute
{
    public string Author { get; }
    public InfoAttribute(string author)
    {
        Author = author;
    }
}

[Info("Hana")]
class Sensor
{
    public string Start() { return "Sensor started"; }
    public string Stop() { return "Sensor stopped"; }
}

[Info("Omar")]
class Valve
{
    public string Open() { return "Valve opened"; }
    public string Close() { return "Valve closed"; }
}

[Info("Priya")]
class Motor
{
    public string Spin() { return "Motor spinning"; }
    public string Halt() { return "Motor halted"; }
}

class Program
{
    static void Main(string[] args)
    {
        Type[] types = { typeof(Sensor), typeof(Valve), typeof(Motor) };
        List<string> lines = new List<string>();
        foreach (Type type in types)
        {
            InfoAttribute info = type.GetCustomAttribute<InfoAttribute>();
            int count = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Length;
            lines.Add(type.Name + " by " + info.Author + ": " + count + " methods");
        }
        lines.Sort();
        foreach (string line in lines)
        {
            Console.WriteLine(line);
        }
    }
}

Key points

  • Each inspected class carries an Info attribute with its author name.
  • GetCustomAttribute reads the attribute data from a type at run time.
  • GetMethods with DeclaredOnly counts only the methods a class declares itself.
  • Sorting the report lines by type name gives a stable order.
  • Reflection reads type information without calling the inspected methods.

In this example, the inspector visits Sensor, Valve, and Motor in turn. For each type it reads the author from the Info attribute. It also counts the methods the type declares itself. The report lines are sorted by type name before printing, so Motor comes first and Valve comes last.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does the inspector use to read each author name?