Reflection
First thing's first, what the heck is reflection?
Reflection is the ability to inspect and manipulate the metadata of your code at runtime. For example, if you wanted to print the properties of an object to the console, you could use reflection to do so:
public void PrintProperties(object obj)
{
var type = obj.GetType();
var properties = type.GetProperties();
foreach (var property in properties)
{
var propertyValue = property.GetValue(obj);
Console.WriteLine($"{property.Name}: {propertyValue}");
}
}
You can use it to invoke methods, set properties, and more, all at runtime.
Setting properties using reflection:
var person = new Person { Name = "Spencer" };
var type = person.GetType();
var nameProperty = type.GetProperty("Name");
nameProperty.SetValue(person, "New Name");
Console.WriteLine(person.Name);
Invoking methods using reflection:
var person = new Person { Name = "Spencer" };
var type = person.GetType();
var method = type.GetMethod("ToString");
var result = method.Invoke(person, null);
Console.WriteLine(result);
You can even instantiate types using reflection:
var person = new Person { Name = "Spencer" };
var type = person.GetType();
var constructor = type.GetConstructor(Type.EmptyTypes);
var result = constructor.Invoke();
Console.WriteLine(result.ToString());
Why in the heck is this useful?
The first time I found out about reflection, I was in an advanced .NET class roughly 1-2 years after I started programming. My first thought is "why the heck would I ever need this?"
If you're thinking this yourself, then you're in good company. I want to show the capability of reflection right now and demonstrate its usefulness a bit more when we get into the ASP.NET Core course.
🌶️🌶️🌶️ Einstein once said "never memorize something that you can look up". What I'm trying to say is that you don't need to memorize this. The use cases for reflection revealed themselves to me throughout my career - it's way more important that you know it exists and know that you can use it when you need it.
Attributes
Attributes are a feature of the .NET runtime that can be used to annotate your code with additional metadata that frameworks can use to add additional behaviors to your code. (Reflection is the component that allows you to read the values from these attributes, which is why we talked reflection first!)
Most languages have some flavor of attributes. I've heard them referred to as "annotations" in some languages and "decorators" in others.
Say for example you have a class that represents an incoming request to create an employee:
public class CreateEmployeeRequest
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Department { get; set; }
}
You may want to add some additional metadata to the class to indicate that we should validate some of the properties of the class:
public class CreateEmployeeRequest
{
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string Department { get; set; }
}
The RequiredAttribute
is there to indicate the property is required. (It's part of the System.ComponentModel.DataAnnotations
namespace and we'll cover that more in the API course.)
Attributes can have additional arguments that are used to modify them. For example, the RequiredAttribute
by itself only means that the property must be non-null. You can add additional attributes to the RequiredAttribute
such as AllowEmptyStrings
to modify the behavior so that empty strings are not allowed either.
[Required(AllowEmptyStrings = false)]
public string FirstName { get; set; }
What can you use attributes on?
You can use attributes on most any declaration in C#. For example, you can use attributes on classes, methods, properties, fields, parameters, and more.
I most commonly use attributes on classes, methods, and properties. We'll see many examples of this in the course on ASP.NET Core APIs, where attributes become really important.
Does Spencer ever declare his own attributes?
I have, but it's not super common to do so. I mainly do it when I'm writing a library that's intended for internal consumption at the organization I'm writing the library for. Most of the time, I'm using what other people have written, but I have absolutely used attributes to add custom behavior to my code.
How do I create my own attribute?
Creating your own attribute is pretty simple. You just need to create a class that inherits from Attribute
.
public class NamedThingAttribute : Attribute
{
public string Name { get; set; }
}
You can then use the attribute like this:
[NamedThing(Name = "Spencer")]
public class MyClass
{
}
You can also use constructors to pass required arguments to the attribute:
public class NamedThingAttribute : Attribute
{
public string Name { get; }
public NamedThingAttribute(string name)
{
Name = name;
}
}
There's a ton that I'm not going to cover here - it's only really important that you know the basics of attributes for the purposes of this course. The main thing that you need to know is that our frameworks can use attributes to modify the behavior of our applications.
These become really important when we start talking about things like ASP.NET Core.