Application Framework Dynamic Object Creation






2.82/5 (8 votes)
Jan 13, 2003
4 min read

77768

464
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:
// 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:
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:
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:
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