Programming Tricks

Dynamic Code Generation with CSharp Reflection

Unleash the Power of CSharp Reflection for Dynamic Code Generation

CSharp reflection is a powerful tool that allows you to examine and manipulate types, methods, properties, and events at runtime. While often associated with advanced scenarios like dependency injection and plugin architectures, it can also be creatively employed for dynamic code generation. This article explores techniques beyond the basics, showcasing how to leverage reflection to build adaptable and extensible applications.

What is CSharp Reflection?

At its core, reflection allows your CSharp code to introspect itself. You can discover the structure of classes, interfaces, and assemblies without knowing their details at compile time. This capability opens the door to creating highly flexible systems.

Dynamic Object Creation

One common use is creating instances of classes at runtime based on configuration or external data.


using System;
using System.Reflection;

public class ExampleClass {
 public string Message { get; set; }
}

public class ReflectionExample {
 public static object CreateInstance(string className, string assemblyName) {
 Assembly assembly = Assembly.Load(assemblyName);
 Type type = assembly.GetType(className);
 return Activator.CreateInstance(type);
 }

 public static void Main(string[] args) {
 object instance = CreateInstance("ExampleClass", "YourAssembly"); // Replace with your assembly name
 if (instance is ExampleClass example) {
 example.Message = "Hello from Reflection!";
 Console.WriteLine(example.Message);
 }
 }
}
Explanation:
  • Assembly.Load() loads the specified assembly.
  • assembly.GetType() retrieves the Type object representing the specified class.
  • Activator.CreateInstance() creates an instance of that Type.

Dynamically Invoking Methods

Reflection also enables you to call methods on objects when you only know their names at runtime. This is especially useful for implementing command patterns or event handling systems.


using System;
using System.Reflection;

public class Calculator {
 public int Add(int a, int b) {
 return a + b;
 }
}

public class MethodInvocationExample {
 public static object InvokeMethod(object obj, string methodName, object[] parameters) {
 Type type = obj.GetType();
 MethodInfo method = type.GetMethod(methodName);
 return method.Invoke(obj, parameters);
 }

 public static void Main(string[] args) {
 Calculator calc = new Calculator();
 object result = InvokeMethod(calc, "Add", new object[] { 5, 3 });
 Console.WriteLine("Result: " + result);
 }
}
Key points:
  • type.GetMethod() gets the MethodInfo object based on the method name.
  • method.Invoke() executes the method with the given object and parameters.

Accessing and Modifying Properties

Beyond method invocation, you can also dynamically get and set property values. This is handy for data binding or serialization scenarios.


using System;
using System.Reflection;

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

public class PropertyAccessExample {
 public static void SetPropertyValue(object obj, string propertyName, object value) {
 Type type = obj.GetType();
 PropertyInfo property = type.GetProperty(propertyName);
 property.SetValue(obj, value);
 }

 public static string GetPropertyValue(object obj, string propertyName) {
 Type type = obj.GetType();
 PropertyInfo property = type.GetProperty(propertyName);
 return property.GetValue(obj).ToString();
 }

 public static void Main(string[] args) {
 Person person = new Person();
 SetPropertyValue(person, "Name", "Alice");
 Console.WriteLine("Name: " + GetPropertyValue(person, "Name"));
 }
}
Explanation:
  • type.GetProperty() retrieves the PropertyInfo object.
  • property.SetValue() sets the property’s value.
  • property.GetValue() retrieves the property’s value.

Advanced Usage and Considerations

While powerful, reflection should be used judiciously. It can introduce performance overhead due to the runtime nature of the operations. Caching reflected types and methods can mitigate some of this overhead. Additionally, be cautious about security implications, especially when dealing with external assemblies.

Final Overview

CSharp reflection provides the means to create highly dynamic and extensible applications. From creating objects to invoking methods and manipulating properties, it enables developers to build systems that can adapt and evolve at runtime. By understanding and applying these techniques, you can unlock new levels of flexibility in your CSharp projects.

Leave a Reply

Your email address will not be published. Required fields are marked *