Dynamically Generate A Class From An Interface Part 1

By Anthony Jackson. Filed in C#  |  
TOP del.icio.us digg

As part of an overall dynamic system that is able to compose objects for use in Dependency Injection, I’d like to be able to take any Interface definition consisting only of properties and turn it into a usable class with an instantiated object being returned.

In order to do this, several parts will be needed:

1.  Method which inspects a defined interface and returns source code for a class

2.  Method which compiles the source code, instantiates an object of the given type and returns it to the caller.

In order to get started, we’ll define a class to actually hold the source code for the class and the name of the class to make it easier as we go through this exercise.  This class should be fairly straightforward and easy to follow:



public class ClassSourceCode

{

public ClassSourceCode(string className, string sourceCode):this()

{

ClassName = className;

SourceCode = sourceCode;

}

public ClassSourceCode()

{

}

public string ClassName { get; set; }

public string SourceCode { get; set; }

}


Our next step is to create a method that will take a look at the properties of the passed in interface and generate source code based on it.  Our method is going to take advantage of generic type parameters to receive the interface that we’ll be working with.  Unfortunately, we don’t have the option of restricting the parameter to an interface, so we’ll have to use the superset class which includes interfaces.  In order to make sure that we really did receive an interface and not a class, we’ll throw in a guard clause.



public ClassSourceCode Generate<T>() where T : class

{

if (!typeof(T).IsInterface)

{

throw new Exception("Interface required for class generation");

}


Next we’ll do a few “housekeeping chores”, create a ClassSourceCode object to be returned and set the ClassName based on the name of the interface; assuming of course that the interface is named using the standard convention of adding a capital I to the front of it’s descriptive name. Since we’ll be doing a great deal of string concatenation, we’ll use a StringBuilder to avoid the performance costs associated with the string class while creating our source code.



ClassSourceCode classSourceCode = new ClassSourceCode();

classSourceCode.ClassName = typeof(T).Name.Remove(0,1);

StringBuilder sourceCode = new StringBuilder();


Now we begin with actually creating the source code for the class.  In order to make the class easier to work with, we’ll set the namespace to the same namespace utilized by the interface passed in and of course the class will implement the passed in interface in it’s definition.



sourceCode.AppendLine("namespace " + typeof(T).Namespace);

sourceCode.AppendLine("{");

sourceCode.AppendLine("public class " + classSourceCode.ClassName + " : " + typeof(T).FullName);

sourceCode.AppendLine("{");


Now we just need code to represent each property within the interface.  Using System.Reflection we’re able to loop through all of the properties described by the passed in interface.



foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())

{


This next section of code is “somewhat optional”, for the system I’m describing their should be no need for Read Only or Write Only properties.  All properties should be Read/Write and would be handled in the very simple else clause in the next section of code.  With that said, I’ve kept this portion in as this code could easily be adapted to handle other instances.  Perhaps you’re looking to create an add-in that will generate class source code from an interface to save yourself time, but will then take the generated class even further, not simply generate and instantiate at run-time as I intend to do.



if (!(propertyInfo.CanWrite &amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp; propertyInfo.CanRead))

{

sourceCode.AppendLine("private " + propertyInfo.PropertyType + " " + propertyInfo.Name.ToLower() + ";");

sourceCode.AppendLine("public " + propertyInfo.PropertyType  + " " + propertyInfo.Name);

sourceCode.AppendLine("{");

if (propertyInfo.CanRead)

{

sourceCode.AppendLine("get");

sourceCode.AppendLine("{");

sourceCode.AppendLine(" return " + propertyInfo.Name.ToLower() + ";");

sourceCode.AppendLine("}");

}

if (propertyInfo.CanWrite)

{

sourceCode.AppendLine("set");

sourceCode.AppendLine("{");

sourceCode.AppendLine(propertyInfo.Name.ToLower() + " = value;");

sourceCode.AppendLine("}");

}

sourceCode.AppendLine("}");

}


This is the simple case for a property that is Read/Write.



else

{

sourceCode.AppendLine("public " + propertyInfo.PropertyType + " " + propertyInfo.Name + " { get; set; }");

}

}

sourceCode.AppendLine("}");

sourceCode.AppendLine("}");


At this point, we have the source code representing our class and simply need to add it to the ClassSourceCode object and return it to the caller.



classSourceCode.SourceCode = sourceCode.ToString();

return classSourceCode;

}

Now that we have a Method which can accept an interface, interrogate it using Reflection and create source code for a class that implements that interface, we can move onto step 2 which is to actually compile the code and instantiate an object based on it.

Dynamically Generate A Class From An Interface Part 2

In this follow up post I’ll walk you step by step through compiling code at runtime using the CSharpCodeProvider and instantiating objects from it.

About Anthony Jackson

Anthony Jackson has written 10 posts in this blog.

Anthony has been developing software professionally since 1996; working primarily with Microsoft technologies such as C#, VB.NET, ASP.NET and MS SQL Server. He has a varied background working in a number of industries, on teams of different sizes including Enterprise Application Development. He often takes on varied roles for projects as well, quickly adapting to what is needed for a given project and is involved in the full life-cycle of software development. This blog and it's articles are entirely the opinion of the author Anthony Jackson and do not reflect the opinions of his employers or clients past, present or future. He currently works for Avanade as a Senior System Analyst and loves working their, but everything written is still just his opinion and does not necessary reflect on any of his employers or clients past, present or future.

2 comments to “Dynamically Generate A Class From An Interface Part 1”

TrackBacks / PingBacks

  1. Pingback
    Dynamically Generate A Class From An Interface Part 3 Unit Tests » Anthony Jackson's Software Development Blog
  2. Pingback
    Dynamic Data Access Layer, Part 1 » Anthony Jackson's Software Development Blog

Leave a Reply

You must be logged in to post a comment.