C# > Advanced C# > Attributes and Reflection > System.Reflection Namespace
Accessing and Using Custom Attributes with Reflection
This code demonstrates how to define a custom attribute and then use reflection to access and utilize the attribute's data at runtime. It showcases a common pattern for adding metadata to classes and members and then querying that metadata to modify behavior.
Defining a Custom Attribute
This section defines a custom attribute called `AuthorAttribute`. The `AttributeUsage` attribute specifies that this attribute can be applied to classes and methods, and only once per target (`AllowMultiple = false`). It has two properties: `Name` and `Version`. The constructor requires a `Name` to be provided when the attribute is applied.
using System;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class AuthorAttribute : Attribute
{
public string Name { get; set; }
public string Version { get; set; }
public AuthorAttribute(string name)
{
Name = name;
Version = "1.0";
}
}
Applying the Custom Attribute
Here, the `AuthorAttribute` is applied to both `MyClass` and `MyMethod`. Notice how the `Name` is provided via the constructor, and `Version` is set as a named parameter when applied to `MyMethod`. This attaches metadata to these elements.
using System;
[Author("John Doe")]
public class MyClass
{
[Author("Jane Smith", Version = "2.0")]
public void MyMethod()
{
Console.WriteLine("MyMethod executed.");
}
}
Using Reflection to Access the Attribute
This code uses reflection to access the `AuthorAttribute` applied to `MyClass` and `MyMethod`. `typeof(MyClass)` gets the `Type` object representing the class. `GetCustomAttribute` retrieves the attribute of the specified type from the class or method. The code then checks if the attribute exists (is not null) and prints the attribute's properties.
using System;
using System.Reflection;
public class Program
{
public static void Main(string[] args)
{
Type type = typeof(MyClass);
// Get Author attribute from the class
AuthorAttribute classAuthor = (AuthorAttribute)Attribute.GetCustomAttribute(type, typeof(AuthorAttribute));
if (classAuthor != null)
{
Console.WriteLine($"Class Author: {classAuthor.Name}, Version: {classAuthor.Version}");
}
// Get Author attribute from the method
MethodInfo method = type.GetMethod("MyMethod");
AuthorAttribute methodAuthor = (AuthorAttribute)Attribute.GetCustomAttribute(method, typeof(AuthorAttribute));
if (methodAuthor != null)
{
Console.WriteLine($"Method Author: {methodAuthor.Name}, Version: {methodAuthor.Version}");
}
}
}
Concepts Behind the Snippet
This snippet demonstrates the fundamental concepts of custom attributes and reflection in C#. Attributes provide a way to add declarative information to your code. Reflection allows you to inspect and manipulate types, methods, fields, and other members at runtime. This combination enables powerful metadata-driven programming.
Real-Life Use Case
A real-life use case could be a plugin system. Attributes could define which plugins are available and their dependencies. At runtime, reflection could be used to discover and load the plugins based on these attributes. Another use case would be serialization, where attributes define how fields should be serialized and deserialized.
Best Practices
Interview Tip
Be prepared to explain the purpose of attributes and reflection, and how they can be used together. Know the difference between compile-time and runtime behavior when using reflection. Understand the performance implications of using reflection, as it can be slower than direct code execution.
When to Use Them
Use attributes when you need to add metadata to your code that affects its behavior at runtime. Use reflection when you need to inspect or manipulate types and members dynamically, typically when the specific types are not known at compile time. Examples are frameworks for serialization, ORMs, or plugin systems.
Memory Footprint
Attributes themselves have a relatively small memory footprint. However, excessive use of reflection can increase memory usage, particularly if you are constantly creating and discarding reflected objects. Optimize your reflection code to minimize object creation.
Alternatives
Alternatives to attributes and reflection include configuration files, code generation, and aspect-oriented programming (AOP) frameworks. Configuration files are good for simple settings, while code generation can provide better performance. AOP can address cross-cutting concerns more cleanly than attributes in some cases.
Pros
Cons
FAQ
-
What is the difference between `Attribute.GetCustomAttribute` and `Type.GetCustomAttributes`?
`Attribute.GetCustomAttribute` retrieves a single attribute of a specific type from a member. `Type.GetCustomAttributes` retrieves an array of all attributes of a specific type (or all attributes if no type is specified) from a type or member. -
Can I modify the behavior of an existing class using attributes and reflection without changing the class's source code?
Yes, you can influence the behavior of an existing class through reflection and by querying attributes associated with it. You can't directly modify the IL, but you can use the metadata to alter program flow or adapt existing behaviors. -
How can I improve the performance of reflection code?
- Cache the results of reflection operations (e.g., MethodInfo objects).
- Avoid unnecessary reflection calls.
- Consider using code generation or expression trees as alternatives for frequently executed reflection code.