Click here to Skip to main content
15,891,375 members
Articles / Programming Languages / C#
Article

Application Framework Dynamic Object Creation

Rate me:
Please Sign up or sign in to vote.
2.82/5 (8 votes)
12 Jan 20034 min read 77.4K   464   42   3
A strategy to implement dynamic object creation for application frameworks.

Abstract

Many developers use third party application frameworks to help take the grunt work out of creating the guts of software. One fine example is the Microsoft Foundation Classes for C++. But what if you want to "roll your own" framework? A nice feature of MFC is the ability to create arbitrary document types and associated views on the fly. This article will discuss one method of dynamic object creation for just such a purpose. I think it's a fitting topic for a new Year() :-)

This article assumes you are moderately accomplished in the .NET Framework. Visual Studio.NET is not required, and in fact, I don't use it here. I suppose it's my CLI bias (that's Command Line Interface for those of you keeping score.) While this sample code is written in C#, it can be applied to any .NET language.

There will be a lot of code, so bear with me, and please note that error handling is omitted in the sample code. In real life I'd always include error handling.

The Right Tool

Sir Winston Churchill once said, "Give us the tools and we shall finish the job." Well, we certainly have the right tool in the System.Reflection assembly, and it's name is ConstructorInfo. A little digging and you find that System.Type can be used to find this tool on any .NET type. Once we have the tool, we can call it's Invoke() method and voilá! We get back an object.

A Base Document

Armed with the tool, we can forge ahead with some code. For this article, we'll be creating a "document manager" capable of dynamically creating and managing requested document objects. To do so, we need to define what a document is. We'll define a base document class from which we can derive all our documents. This base class will feature: an ID, a title, a "path", a modified flag; definitions for basic persistence; and an event to notify interested parties that it's been modified:

C#
//   Our Document Modified Handler
public delegate void   DocumentModifiedHandler(Document theDoc);

//   Our Base Document
public class   Document
{
   //   storage

   private Guid   m_Id;
   protected string   m_strTitle;
   protected string   m_strPath;
   protected bool   m_bModified;

   //   ctor

   public   Document()
   {
      m_Id = Guid.NewGuid();
      m_strTitle = "";
      m_strPath = "";
      m_bModified = false;
   }

   //   properties

   public Guid   Id   {   get   {   return m_Id;   }   }

   public string   Title
   {
      get   {   return m_strTitle;   }
      set
      {
         m_strTitle = value;
         FireModified();
      }
   }

   public string   Path   {   get   {   return m_strPath;   }   }

   public bool   IsModified   
    {   get   {   return m_bModified;   }   }

   //   methods

   virtual public void   Save(string path)
   {
      m_strPath = path;
      m_bModified = false;
   }

   virtual public void   Load(string path)
   {
      m_strPath = path;
      m_bModified = false;
      FireModified();
   }

   protected void   FireModified()
   {
      if (this.Modified != null)   Modified(this);
   }

   //   events

   public event DocumentModifiedHandler   Modified;
}

Type Info

On our way to dynamic creation, we need some way to specify what type of document is available for creation. We create a class to handle this need:

C#
public class   DocumentType
{
   //   storage

   private Guid   m_Id;
   private string   m_strName;
   private string   m_strExtension;
   private Type   m_DocType;

   //   ctor

   public   DocumentType(string name, string extension, Type type)
   {
      m_Id = Guid.NewGuid();
      m_strName = name;
      m_strExtension = extension;
      m_DocType = type;
   }

   //   properties

   public Guid   Id   {   get   {   return m_Id;   }   }
   public string   Name   {   get   {   return m_strName;   }   }
   public string   Extension   
     {   get   {   return m_strExtension;   }   }
   public Type   DocType   {   get   {   return m_DocType;   }   }
}

Notice that we squirrel away a System.Type. This is key for our framework. We also store some information that could be used to assist in displaying "new" document types for the UI portion of our framework.

The Glue

The last piece of the framework we need to implement is some way to manage all the documents and their creation. For this we define a base DocumentManager class that has the basic functionality we need:

  • Management of document types including registering new types, removing types, and their enumeration.
  • Management of the documents themselves, including creation, removal and enumeration.

I won't list the entire class, just the most interesting part -- dynamic document creation:

C#
virtual public Document   CreateDocument(Guid doctypeid)
{
   DocumentType   oDocType = (DocumentType)m_DocTypes[doctypeid];

   if (null == oDocType)   return null;

   System.Reflection.ConstructorInfo oConstructor = 
         oDocType.DocType.GetConstructor(Type.EmptyTypes);
   Document  oDoc = (Document)oConstructor.Invoke(null);

   m_Documents.Add(oDoc.Id, oDoc);

   return oDoc;
}

We now have our framework bits!

The important thing here is the call to GetConstructor. If we wanted an alternate constructor, we'd create an array of Types containing the constructor parameter types. I leave selecting from multiple constructors up to the reader. For our framework, the default constructor is sufficient, and makes things simple. For a dynamic "view" framework similar to this one, a ViewManager could use a View constructor that takes one argument of type Document.

Wielding the Tool

The sample code creates some Document derivatives and uses them to illustrate using our framework. It's important to register each Document we intend on creating dynamically. The following code shows how a documents are registered:

C#
DocumentManager   oDM = new DocumentManager();

//   register some types
oDM.RegisterDocType("Text File", "txt", typeof(TextDocument));
oDM.RegisterDocType("Image File", "jpg", typeof(ImageDocument));
oDM.RegisterDocType("Remotely Stored File", "", typeof(RemoteDocument));

We should probably squirrel away the IDs returned by the registration process so we can use them later. The sample code just enumerates them for creation. If all compiled well, we should see the following output when we run the sample code:

Registered Document Types 3:
   Remotely Stored File, nspace.Samples.Framework.RemoteDocument, 
           1fad0238-cbe6-4428-999d-8652f6039807
   Image File, nspace.Samples.Framework.ImageDocument, 
           8d5b4b55-4401-4b90-8a6f-2478e5cd8404
   Text File, nspace.Samples.Framework.TextDocument, 
           b0f5f9fc-fbd0-4a62-bea3-d31153d9ec21

Creating instances of each doc type...

Created a remote document with Id fc223fa0-d312-4052-8119-c844d0c72950
Created an image document with Id 2f9f33d4-ec13-418d-a5b7-3330be660060
Created a text document with Id 8275ac8e-a1e4-4f3f-9691-e8ba4fa1d2b0

Of course, the GUIDs you will see will be different whenever you run the sample.

Closing Remarks

Application frameworks can be daunting to design and implement. Hopefully this article has taught you a bit about the .NET Framework and whetted your appetite for creating useful and reusable code. I recommend reading the .NET Framework Documentation for further information.

Stay tuned for future articles...

Building the Sample Code

Unzip the source files to the folder of your choice. Start a shell (cmd.exe) and type nmake. You may have to alter the Makefile to point to the correct folder where your .NET Framework libraries exist.

History

  • 2003-01-13 Initial Revision / Doc Formatting

References

  • Microsoft .NET Framework SDK Documentation

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Chief Technology Officer
United States United States
20+ years as a strategist at the intersection of business, design and technology.

Comments and Discussions

 
Generalthanks, this was very helpful and easy to understand Pin
billy p7-Dec-06 8:21
billy p7-Dec-06 8:21 
I have a base class and an unknown number of derived classes. I wanted the base class to be able to instantiate objects of any derived types (helpful with Object binding to DataGridViews). Your article described using the constructorinfo class very nicely.

Thanks

GeneralAlternate method Pin
ian mariano13-Jan-03 9:14
ian mariano13-Jan-03 9:14 
GeneralRe: Alternate method Pin
malby30-Nov-03 17:35
malby30-Nov-03 17:35 

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.