let's take a look at an implementation of our Person class
[DebuggerDisplay("{DebuggerDisplay()}")]
class Person {
static int
_runningId = 0;
public int Id { get; } = _runningId++;
public string
FirstName { get; set; }
public string LastName
{ get; set; }
public DateTime Birthdate { get; set; }
public Person() { }
public Person(string
FirstName, string LastName)
: this()
{
this.FirstName = FirstName;
this.LastName = LastName;
}
public Person(string
FirstName, string LastName, DateTime Birthdate)
:
this(FirstName, LastName) {
this.Birthdate = Birthdate;
}
public int GetAge()
{
if (Birthdate == new DateTime())
return -1;
var today = DateTime.Now;
var age = today.AddYears(-Birthdate.Year).Year;
return Birthdate.AddYears(age) > today ? --age : age;
}
private string
DebuggerDisplay() {
var age = GetAge();
var result = $"{FirstName} {LastName}";
return age > -1 ? $"{result} is {age}" : result;
}
}
now we can use reflection to inspect the details of our class
class Program
{
static void Main(string[] args)
{
Type pt = typeof(Person);
//list
attributes
var attributes = Attribute.GetCustomAttributes(pt);
foreach (var attr in attributes)
Console.WriteLine(attr.GetType().Name);
//list
properties
foreach (var prop in pt.GetProperties())
Console.WriteLine($"{prop.Name}
{prop.PropertyType}");
//list
constructors
foreach (var con in pt.GetConstructors())
{
Console.WriteLine($"constructor with {con.GetParameters().Length}
parameters");
foreach (var p in con.GetParameters())
Console.Write($"{p.ParameterType} {p.Name}, ");
Console.WriteLine("\n");
}
//list methods
foreach (var mi in pt.GetMethods())
Console.WriteLine(mi.Name);
}
}
This allows us to see what's inside of our class definition
We can also inspect at the assembly level
static void Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
Console.WriteLine(assembly.FullName);
foreach (Type t in assembly.GetTypes())
{
Console.WriteLine($"Assembly Type: {t.Name}");
Console.WriteLine("\tConstructors");
foreach (var con in t.GetConstructors())
{
var parCount = con.GetParameters().Length;
Console.Write($"\t\tconstructor with {parCount} parameters");
if (parCount == 0)
{
Console.WriteLine();
continue;
}
Console.Write("\n\t\t\t");
foreach (var p in con.GetParameters())
Console.Write($"{p.ParameterType} {p.Name}, ");
Console.WriteLine();
}
Console.WriteLine("\n\t\tFields");
foreach (FieldInfo fi in t.GetFields())
Console.WriteLine($"\t\t\t{fi.Name} ({fi.FieldType})");
Console.WriteLine("\t\tProperties");
foreach (PropertyInfo pi in
t.GetProperties())
Console.WriteLine($"\t\t\t{pi.Name} ({pi.PropertyType})");
Console.WriteLine("\t\tMethods");
foreach (MethodInfo mi in t.GetMethods())
Console.WriteLine($"\t\t\t{mi.Name} ({mi.ReturnType})");
}
}
}
class Program
{
static void Main(string[] args)
{
var P1 = new Person("John", "Smith", new DateTime(1984, 1, 31));
MethodInfo debbuggerDisplay = P1.GetType().GetMethod("DebuggerDisplay",
BindingFlags.NonPublic | BindingFlags.Instance);
Console.WriteLine(debbuggerDisplay.Invoke(P1, null));
}
}