Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C# 3.5

Reflection optimization techniques

Rate me:
Please Sign up or sign in to vote.
4.95/5 (63 votes)
29 May 2013CPOL9 min read 137.3K   203   60
The article presents some .NET techniques for using Reflection optimally and efficiently.

Introduction

Reflection is one of the very powerful features in the Microsoft .NET framework. It provides a rich set of APIs under the namespace System.Reflection for loading and handling assemblies and objects besides retrieving meta data information such as method information, property information, and attributes (annotations) dynamically at runtime.

Using Reflection indeed makes developers’ life easy, however it should be used to a minimum and in other words only when it is required; it impacts the performance to a great extent. There are different techniques that help using reflection in an efficient way.

Often times we use reflection without realizing the cost that it comes at. In this article we will look at some techniques that help in using reflection optimally.

Solution

In this article, we will discuss some of the techniques that can be used for either avoiding reflection completely or at least using it repetitively. In the remainder of the article we will look at some scenarios where reflection can be used effectively.

Scenario 1 – Dynamic invocation of a method

If the names of methods/members to be invoked on an object created at run time are known at the time of development then instead of using reflection for dynamically invoking them, use interfaces and call them statically.

Example of completely dynamic invocation

C#
public void DynamicExecution()
{
    Type objType = Type.GetType("DynamicExecution.Test.DynamicClass");

    object obj = Activator.CreateInstance(objType);
    MethodInfo mInfo = objType.GetMethod("AddNumbers",
	new Type[] { typeof(int), typeof(int) });

    // Executing AddNumbers method dynamically on obj
    mInfo.Invoke(obj, new object[] { 1, 5 });

    PropertyInfo pInfo = objType.GetProperty("ID");

    // Set property ID dynamically on obj
    pInfo.SetValue(obj, "TEST_ID", null );

} 

Disadvantages of using the above code are: 

  1. Every dynamic call to a method or property is several times more expensive than a static call to the same method or property.
  2. Type safety of method parameters and property values is not checked during compile time and code can break at runtime if the parameters provided are not of the appropriate types.
  3. Code is lengthier than the optimized code and hence less maintainable.

Example of optimized code

C#
Public void OptimizedDynamicExecution()
{
    Type objType = Type.GetType("DynamicExecution.Test.DynamicClass");

    IDynamicClass obj = Activator.CreateInstance(objType) as IDynamicClass;

    if (null != obj)
    {
        // Executing AddNumbers method statically on obj
        int result = obj.AddNumbers(1, 5);

        // Set property ID statically on obj
	// The code will not compile if value is assigned as "TEST_ID"
        obj.ID = 10; 
    }
}

// Interface to be consumed by OptimizedDynamicExecution API
public interface IDynamicClass
{
    int ID { get; set; }

    int AddNumbers(int a, int b);
} 

Benefits of using the above code are: 

  1. Fast execution speed as the method is executed statically.
  2. Type safety achieved by making use of an interface.
  3. The same interface can be used at other places as appropriate.
  4. Shorter code for making method calls, etc.

Scenario 2 – Reading custom attributes from a class

Custom attributes (Annotations) are used to provide additional information about an assembly, a class, or a member of a class, so if a class is decorated with an attribute that is required every time you create an instance of that class then it is advisable to cache that value in a static variable so that reflection is used only for the first instance and can be avoided for subsequent instances.

Following is an example of an entity class:

C#
[Table(Name="Employees")]
public class Employee : Entity
{
    [PrimaryKey]
    public int Id { get; set; }
    
    public string Name { get; set; }
    public string Address { get; set; }
    public DateTime DOB { get; set; }

} 

The above code is an example of an entity class Employee which corresponds to a table in the database called “Employees”. If you look at it carefully, the property Id is decorated with an attribute called PrimaryKey. All the members including the class itself that are decorated with attributes have some special meaning which is required by the consumer of this class for processing each of its instances.

In order to retrieve this information, we have to apply reflection to read the attributes (annotations) from this class. It will be very expensive if it is repeated for every instance of this class. A better idea from a performance perspective would be to read it only for the first time and cache it for all subsequent instances.

Example of retrieving attributes information dynamically for every instance

C#
public class Entity
{
    public Entity()
    {
        Type curType = this.GetType();

        // The following reflection code will be executed every time 
        // an instance of this class is created.
        object[] tableAttributes =
		curType.GetCustomAttributes(typeof(TableAttribute), true);

        if(null != tableAttributes && tableAttributes.Count() > 0)
        {
            // Retrieve the attribute information
        }

        // Use the attribute information here 
    }
}

Disadvantages of using the above code are

  1. Every time an object of this class is created, the attribute information is dynamically retrieved using reflection.
  2. Retrieving attribute information using reflection is a very expensive operation.

Following example demonstrates the concept of caching attribute information for achieving better performance: 

C#
// C# structure to hold table information
public struct TableInfo
{
    public string TableName;
    public string PrimaryKey;
} 

In this example code below, the constructor looks up a static dictionary object for the existence of table information using the current entity class’ type as the key. It will not be found for the first time and that’s when the attribute information will be retrieved using reflection and be kept in the collection for subsequent retrievals. This is how we save the cost of reflection. 

C#
public class Entity
{
    private static Dictionary<Type, TableInfo> tableInfoList = 
                                         new Dictionary<Type, TableInfo>();

    public Entity()
    {
        Type curType = this.GetType();
        TableInfo curTableInfo;
        
        if (!tableInfoList.TryGetValue(curType, out curTableInfo))
        {
            lock (this)
            {
                // double check to ensure that an instance is not 
                // created before this lock
                if (!tableInfoList.TryGetValue(curType, out curTableInfo))
                {
                    object[] tableAttributes =
			curType.GetCustomAttributes(typeof(TableAttribute), true);

                    if(null != tableAttributes && tableAttributes.Count() > 0)
                    {
                        curTableInfo = new TableInfo();
                        curTableInfo.TableName = ((TableAttribute) tableAttributes[0]).Name;
                    }
                }
            }
        }

        // use curTableInfo here 
    }
}

The example code above demonstrates how information can be retrieved from custom attributes once and be used for subsequent instances of the same class without having to run the reflection code every time. 

Benefits of using this technique are:

  1. Reflection is applied only for the first time and a cached copy of the information is used for all subsequent times.
  2. The cost of reflection is minimized by using the caching technique. 

Scenario 3 – Dependency Injection

Often times we need to inject dependencies in some pieces of code for decoupling the implementation logic of a particular functionality form the logic of its consumer so that the implementation can be provided by different providers at a later point of time. To handle this scenario we normally allow the user to configure the assembly and the class to be injected in the configuration file.

In such a scenario the application would require to load the assembly and dynamically create the instance of the dependency class using reflection every time it is needed; this operation is very expensive in terms of processing and would result in poor performance in case of heavy traffic to this part of the application.

Microsoft .NET light-weight code generation helps in resolving the problem of creating an instance of any object that is not known at design time. It provides a set of APIs under the namespace System.Reflection.Emit for creating assemblies, classes, and methods etc., programmatically.

This technique can be used for reducing the overhead of creating objects using reflection every time by creating a dynamic method that would statically create the instance of the required class. This method’s delegate can then be cached in a dictionary for subsequent invocations.

Following example demonstrates this concept  

C#
// Contract for the dependency class
public interface ISecurityProvider
{
    bool ValidateUser(string userId, string password);
    List<User> GetUsersList();
}

// Actual implementation of the dependency class to be instantiated
public interface DefaultSecurityProvider : ISecurityProvider
{
    public bool ValidateUser(string userId, string password)
    {
        ...
    }
    public List<User> GetUsersIist()
    {
        ...
    }
}

Example of completely dynamic invocation

C#
// Method that needs to create the instance of DefaultSecuirtyProvider
// class dynamically
private void CreateInstance()
{
    Type classType =
        Type.GetType("DefaultSecurityProvider, AssemblyName");
    
    // Follwoing code creates the instacne of dependency class
    // dynamically using reflection every time.
    ISecurityProvider employeeInstance = Activator.CreateInstance(classType) as ISecurityProvider;
} 

Disadvantages of using the above code are: 

  1. Every time an instance of the dependency class is required, it will be created dynamically using reflection.
  2. Creating an object dynamically using reflection is a very expensive operation. 

Following code demonstrates how the cost of reflection can be avoided:  

C#
// Method that needs to create the instance of DefaultSecuirtyProvider
// class dynamically
private void CreateInstance()
{
    Type classType = 
   Type.GetType("DefaultSecurityProvider, AssemblyName");

    // Following function returns the delegate for instantiating the required
    // object statically
    CreateInstanceDelegate createInstance = ObjectInstantiater(classType);

    // Executing the delegate for creating an instance of the dependency class
    ISecurityProvider employeeInstance = createInstance() as ISecurityProvider;
}  

Following delegate will be used for mapping the method dynamically created using Microsoft .NET light weight code generation technique 

C#
// Delegate for holding object instantiator method
public delegate object CreateInstanceDelegate(); 

Following dictionary object will hold the delegates of the methods dynamically created for instantiating dependency class objects

C#
// Dictionary for holding object instantiator delegates
private static Dictionary<Type, CreateInstanceDelegate> 
    _createInstanceDelegateList = new Dictionary<Type, CreateInstanceDelegate>();

Following function creates a method programmatically at run time for instantiating the objects of a given type. 

C#
// Function that creates the method dynamically for creating the instance
// of a given class type
public static CreateInstanceDelegate ObjectInstantiater(Type objectType)
{
    CreateInstanceDelegate createInstanceDelegate;

    if (!_createInstanceDelegateList.TryGetValue(objectType, 
        out createInstanceDelegate))
    {
        lock (objectType)
        {
            if (!_createInstanceDelegateList.TryGetValue(objectType, 
         out createInstanceDelegate))
            {
                // Create a new method.        
                DynamicMethod dynamicMethod =
                    new DynamicMethod("Create_" + objectType.Name,
	           objectType, new Type[0]);

                // Get the default constructor of the plugin type
                ConstructorInfo ctor = objectType.GetConstructor(new Type[0]);

                // Generate the intermediate language.       
                ILGenerator ilgen = dynamicMethod.GetILGenerator();
                ilgen.Emit(OpCodes.Newobj, ctor);
                ilgen.Emit(OpCodes.Ret);

                // Create new delegate and store it in the dictionary
                createInstanceDelegate = (CreateInstanceDelegate)dynamicMethod
                    .CreateDelegate(typeof(CreateInstanceDelegate));
                _createInstanceDelegateList[objectType] = createInstanceDelegate;
            }
        }
    }
    return createInstanceDelegate; // return the object instantiator delegate
}  

The above code demonstrates how an object of any class can be created statically that is not known at design time and only recognized by its interface (contract).

In the above example we created a proxy method dynamically using APIs provided in the System.Reflection.Emit namespace that creates the instance of the dependency class statically. Once this method is created we store it in a dictionary against the type of the dependency class as the key so that for all subsequent times we can pull this delegate from the dictionary and use it.

Benefits of using this technique are:

  1. The object of the dependency class is created statically using the Object instantiating method.
  2. This technique helps in avoiding reflection for object instantiation.  

Scenario 4 - Setting the property values of an ORM entity dynamically

In all ORM frameworks, there are entity classes that correspond to tables in the database. The framework applies reflection for reading the values of the properties (columns) and setting the values of the properties (columns) from each instance of an entity class. This operation is very expensive and could reduce performance to a great extant. This can be handled by generating dynamic methods in the same way as it was demonstrated in scenario 3, however in this example we will achieve this using a new feature introduced in .NET Framework 3.5 called Expression Trees.

Following example demonstrates this concept  

C#
// Entity class Employees
public class Employees
{
    public int EmployeeID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public DateTime BirthDate { get; set; }
}

// Employees list to be populated with data retrieved from the data reader
List<Employees> empList = new List<Employees>();  

Following code fills the list of employees from the data reader 

C#
// Employees list to be populated with data retrieved from the data reader
List<Employees> empList = new List<Employees>();

using(SqlConnection con = new SqlConnection(@"Data Source=localhost\SQLEXPRESS;
   Initial Catalog=Northwind;Integrated Security=True"))
{
    SqlCommand cmd = new SqlCommand("Select * from employees");
    cmd.Connection = con;
    con.Open();

    // Call the ReadList method seding Employees as the type of entity
    // and the data reader as the parameter
    using (SqlDataReader reader = cmd.ExecuteReader())
    {
        empList = ReadList<Employees>(reader);
    }
}

Example of setting the property values of an entity class dynamically using reflection

C#
// Method to be called for getting the list of entity class
// filled with data from the data reader. 
public List<T> ReadList<T>(SqlDataReader reader) where T : new()
{
    var list = new List<T>();

    while (reader.Read())
    {
        T entity = new T();
        Type entityType = typeof(T);
        foreach(var entityProperty in entityType.GetProperties())
        {
            // Using reflection for setting the value of each 
            // property of the entity.
            entityProperty.SetValue(entity, reader[entityProperty.Name], null);
        }

        list.Add(entity);
    }
    return list;
}

Disadvantages of using the above code are:

  1. Setting the properties of an object using reflection is a very heavy operation.
  2. The developer has to take care of type safety while setting the value of the property

The following example demonstrates how values can be read from an object of SqlDataReader and added to a list of an entity without having to write event static code as well as without applying reflection repeatedly.

Following function iterates through the data reader and populates a list of entities with relevant values

C#
// Method to be called for getting the list of entity class
// filled with data from the data reader. 
public List<T> ReadList<T>(SqlDataReader reader)
{
    var list = new List<T>();  
    Func<SqlDataReader, T> readRow = GetReader<T>(); 

    while (reader.Read())
    {
        list.Add(readRow(reader));
    }
    return list;
}  

Following dictionary holds the delegate of the method generated dynamically for populating the data table values into the entity list  

C#
// Cache store for memorizing the delegate for later use
ConcurrentDictionary<Type, Delegate> ExpressionCache = 
                       new ConcurrentDictionary<Type, Delegate>();

Following method creates a function programmatically using Expression tree feature of Microsoft .NET. The dynamically generated function is saved as a delegate in a dictionary for later retrieval 

C#
// Method for creating the dynamic funtion for setting entity properties
public Func<SqlDataReader, T> GetReader<T>()
{
    Delegate resDelegate;
    if (!ExpressionCache.TryGetValue(typeof(T), out resDelegate))
    {
        // Get the indexer property of SqlDataReader 
        var indexerProperty = typeof(SqlDataReader).GetProperty("Item",
        new[] { typeof(string) });
        // List of statements in our dynamic method 
        var statements = new List<Expression>();
        // Instance type of target entity class 
        ParameterExpression instanceParam = Expression.Variable(typeof(T));
        // Parameter for the SqlDataReader object
        ParameterExpression readerParam =
            Expression.Parameter(typeof(SqlDataReader));

        // Create and assign new T to variable. Ex. var instance = new T(); 
        BinaryExpression createInstance = Expression.Assign(instanceParam,
            Expression.New(typeof(T)));
        statements.Add(createInstance);

        foreach (var property in typeof(T).GetProperties())
        {
            // instance.Property 
            MemberExpression getProperty =
            Expression.Property(instanceParam, property);
            // row[property] The assumption is, column names are the 
            // same as PropertyInfo names of T 
            IndexExpression readValue =
                Expression.MakeIndex(readerParam, indexerProperty,
                new[] { Expression.Constant(property.Name) });

            // instance.Property = row[property] 
            BinaryExpression assignProperty = Expression.Assign(getProperty,
                Expression.Convert(readValue, property.PropertyType));

            statements.Add(assignProperty);
        }
        var returnStatement = instanceParam;
        statements.Add(returnStatement);

        var body = Expression.Block(instanceParam.Type,
            new[] { instanceParam }, statements.ToArray());

        var lambda =
        Expression.Lambda<Func<SqlDataReader, T>>(body, readerParam);
        resDelegate = lambda.Compile();

        // Cache the dynamic method into ExpressionCache dictionary
        ExpressionCache[typeof(T)] = resDelegate;
    }
    return (Func<SqlDataReader, T>)resDelegate;
}   

In the above code, we created a function dynamically using .NET expression tree feature that sets the values of an entity object after reading them from a SqlDataReader object passed to it as a parameter. This method is compiled and cached in a dictionary so that it can be used for all subsequent times without having to recreate it.

Benefits of using this technique are:

  1. The developer is not required to write code for setting values of any entity.
  2. The expression tree created for the method can be serialized and transferred across process boundaries.
  3. It is easier to create an expression tree using the .NET APIs rather than writing the IL code.

Conclusion

We looked at four scenarios where the reflection technique was used in an inappropriate way that leads to poor performance and we also looked the techniques that can be used for improving the performance by either using an alternative to reflection or using the caching mechanism for avoiding the use of reflection repetitively.

Caching technique used in this article ensures that the information is retrieved using reflection only once and used multiple times.

Dynamic code generation using Light weight code generation technique and Expression Trees help in creating static proxy methods to avoid reflection in scenarios such as instantiating objects and setting/getting property values etc.

Further Reading

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Symphony Teleca Corporation
India India
I am Ajay Jain, a Senior Architect with 16+ years of experience in Microsoft technologies. I work at Symphony Teleca Corporation, Bangalore. I specialize in technologies like Microsoft.Net, C#, SOA, Enterprise Architecture, SQL Server, JavaScript and Azure.

Comments and Discussions

 
SuggestionGetCustomAttributes vs IsDefined Pin
Andrew Rissing5-Dec-12 4:24
Andrew Rissing5-Dec-12 4:24 
GeneralRe: GetCustomAttributes vs IsDefined Pin
Jain, Ajay5-Dec-12 7:35
Jain, Ajay5-Dec-12 7:35 
GeneralRe: GetCustomAttributes vs IsDefined Pin
Jain, Ajay6-Dec-12 4:45
Jain, Ajay6-Dec-12 4:45 
BugRegarding scenario 2 Pin
René Wolferink4-Dec-12 22:42
René Wolferink4-Dec-12 22:42 
GeneralRe: Regarding scenario 2 Pin
Jain, Ajay5-Dec-12 7:44
Jain, Ajay5-Dec-12 7:44 
GeneralRe: Regarding scenario 2 Pin
René Wolferink5-Dec-12 21:43
René Wolferink5-Dec-12 21:43 
GeneralRe: Regarding scenario 2 Pin
Member 89861897-Dec-12 4:59
Member 89861897-Dec-12 4:59 
GeneralRe: Regarding scenario 2 Pin
Jain, Ajay7-Dec-12 8:03
Jain, Ajay7-Dec-12 8:03 
GeneralRe: Regarding scenario 2 Pin
Member 89861898-Dec-12 0:05
Member 89861898-Dec-12 0:05 
AnswerRe: Regarding scenario 2 Pin
Matt T Heffron10-Dec-12 12:57
professionalMatt T Heffron10-Dec-12 12:57 
GeneralMy vote of 5 Pin
Programm3r4-Dec-12 21:20
Programm3r4-Dec-12 21:20 
GeneralMy vote of 5 Pin
LucianPopescu4-Dec-12 21:19
LucianPopescu4-Dec-12 21:19 
very nice and clear advantages and disadvantages comparison. very helpful Smile | :) thank you

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.