MSDN Documentation

.NET | Advanced Topics

Advanced .NET Reflection

Reflection in .NET provides the ability to inspect and manipulate metadata and code at runtime. This is a powerful technique that allows you to dynamically examine types, members, and assemblies. This section delves into advanced concepts and practical applications of reflection.

Note: While reflection is a powerful tool, it can come with performance overhead. Use it judiciously and consider alternative approaches when performance is critical.

Understanding the Core Concepts

Reflection is primarily facilitated by types in the System.Reflection namespace. Key types include:

Dynamic Invocation of Members

One of the most common uses of reflection is to dynamically invoke methods and access properties/fields. This is especially useful in scenarios like serialization, ORM frameworks, and plugin architectures.

Invoking a Method Dynamically

To invoke a method, you first need to get a MethodInfo object representing the method you want to call. Then, you can use the Invoke method.


using System;
using System.Reflection;

public class MyClass
{
    public void Greet(string name)
    {
        Console.WriteLine($"Hello, {name}!");
    }
}

// ... in another part of your code ...

Type type = typeof(MyClass);
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("Greet");

if (method != null)
{
    object[] parameters = { "World" };
    method.Invoke(instance, parameters); // Output: Hello, World!
}
            

Accessing Properties Dynamically


using System;
using System.Reflection;

public class MyData
{
    public string Name { get; set; }
}

// ...

Type dataType = typeof(MyData);
object dataInstance = Activator.CreateInstance(dataType);

PropertyInfo nameProperty = dataType.GetProperty("Name");

if (nameProperty != null)
{
    nameProperty.SetValue(dataInstance, "Reflection Example");
    object value = nameProperty.GetValue(dataInstance);
    Console.WriteLine($"Name: {value}"); // Output: Name: Reflection Example
}
            

Working with Attributes

Attributes provide a way to add declarative information to your code. Reflection allows you to discover and use these attributes at runtime.

Important: Attributes are a cornerstone for building robust reflection-based frameworks.

Retrieving Attributes from a Type


using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomDocumentationAttribute : Attribute
{
    public string Description { get; }
    public CustomDocumentationAttribute(string description)
    {
        Description = description;
    }
}

[CustomDocumentation("A sample class for demonstration.")]
public class DocumentedClass
{
    [CustomDocumentation("A sample method.")]
    public void DoSomething() { }
}

// ...

Type docType = typeof(DocumentedClass);
CustomDocumentationAttribute classAttr = (CustomDocumentationAttribute)Attribute.GetCustomAttribute(docType, typeof(CustomDocumentationAttribute));

if (classAttr != null)
{
    Console.WriteLine($"Class Description: {classAttr.Description}"); // Output: Class Description: A sample class for demonstration.
}

MethodInfo methodInfo = docType.GetMethod("DoSomething");
CustomDocumentationAttribute methodAttr = (CustomDocumentationAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(CustomDocumentationAttribute));

if (methodAttr != null)
{
    Console.WriteLine($"Method Description: {methodAttr.Description}"); // Output: Method Description: A sample method.
}
            

Advanced Techniques

Dynamic Assembly Loading


using System;
using System.Reflection;

// Assume "MyExternalAssembly.dll" exists and contains a class named "ExternalClass"
// with a public method "Execute".

try
{
    Assembly externalAssembly = Assembly.LoadFrom("MyExternalAssembly.dll");
    Type externalType = externalAssembly.GetType("MyExternalAssembly.ExternalClass");

    if (externalType != null)
    {
        object externalInstance = Activator.CreateInstance(externalType);
        MethodInfo executeMethod = externalType.GetMethod("Execute");

        if (executeMethod != null)
        {
            executeMethod.Invoke(externalInstance, null);
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error loading or executing assembly: {ex.Message}");
}
            

Performance Considerations

Reflection involves significant overhead because it bypasses the compiler's optimizations. Operations like:

are all computationally more expensive than direct code execution. When performance is critical, consider these alternatives:

Use Cases

Tip: For frequent reflection operations on the same type, cache the Type and MemberInfo objects to reduce repeated lookups.