Tools Used
Visual C# .NET, WithClass 2000 Enterprise(Trial Version)
Using the power of .NET and the power of COM InterOperability through WithClass 2000, you can view the System.Drawing library in a rough UML diagram. The first cut in this article doesn't bring in relationships, but Part II of this article will show you how to bring relationships into the diagram. If you want to try out the code in this article, and don't have the full version of WithClass 2000 Enterprise, you can download the trial version of the product at Microgold's Website.
Reflection is a powerful part of UML that allows you to view details about classes at runtime. When I refer to classes, I mean any class that is actively running in the system. Therefore we can view any library we bring through in the using statement. Currently this does not include code, but we can at least look at fields, properties, methods, class details and other interesting aspects of the library. I've referenced Hari Shankar's article, Reflection in .NET, to help me get through this example. It's worth taking a look at.
WithClass is a COM component as well as an application. The user can access WithClass and draw classes, relationships, states, interactions, or almost any diagramming capability UML supports, through its COM interface. To construct a new UML WithClass document to work with, let's examine the code below:
public class WithClassReflector
{
public Type[] TheTypes;
// Launch WithClass and construct a COM Application Object for it
public With_Class.Application wcApp = new With_Class.Application();
public With_Class.IWithClass myDoc;
public WithClassReflector()
{
//
// TODO: Add Constructor Logic here
//
// Create a NewFile in our application
// And assign a document reference to it
wcApp.ActiveDocument.NewFile();
myDoc = (With_Class.IWithClass)wcApp.ActiveDocument;
}
Before this code could compile, I needed to right click on the solution explorer and add a Reference to WithClass under the COM Tab. I also needed to add the necessary using statements shown below directly above the class to access reflection and Interoperability:
using System.Reflection; // needed to use the power of reflection
using System.Runtime.InteropServices;
// needed to use WithClass along with a Reference in the project
Now we are ready to roll. I've Created a separate class WithClassReflector (as seen above), to construct the reflection aspects of the Drawing library. Below is the method that does most of the work for extracting the information:
public void ExtractAssembly()
{
Assembly theAssembly; // assembly object
// get a hold of the path on your system for the location of the Drawing Assembly
// this string may vary depending upon where the System.Drawing.dll is on your system
string assemblyPath = "c:\\winnt\\microsoft.net\\framework\\v1.0.2204\\System.Drawing.dll";
// Load up the assembly into the assembly object
theAssembly = System.Reflection.Assembly.LoadFrom(assemblyPath);
// Get the collection of types in the Drawing Assembly (each type is generally a class or interface or structure)
TheTypes=theAssembly.GetTypes();
int count = 0;
// cycle through each class and extract method, field, and property information
foreach(Type t in TheTypes)
{
.....
}
Basically, the code just cycles through each class in our assembly and we use WithClass to create the classes and class details in a viewable drawing. Below is the part of the code that initially creates a class in WithClass:
// Create a new class from the reflected name t.Name in WithClass 2000 at position 30,20
With_Class.IClass c1 = myDoc.NewClass(30, 20, t.Name);
// Tell the created class to show parameter information, type information, property information, and Visibility
// information.
c1.ShowParameters = true;
c1.ShowProperties = true;
c1.ShowType = true;
c1.ShowVisibility = true;
Now let's look at one of the detailed code pieces we can extract from reflection, methods. The code below extracts the methods of a class into WithClass's current class, c1:
// Get the methods for this class using reflection
MethodInfo[] mInfo=t.GetMethods();
// Cycle through each method in the class, and add it to the Class in WithClass 2000
foreach(MethodInfo m in mInfo)
{
// Create a new operation in WithClass with the next reflected method
With_Class.IOperation wcOp = c1.NewOperation(m.Name);
// Determine the visibility for the method
if (m.IsPrivate)
{
wcOp.Visibility = "private";
}
else if (m.IsPublic)
{
wcOp.Visibility = "public";
}
// Assign the return type in WithClass
wcOp.ReturnType = m.ReturnType.ToString();
// Cycle through each parameter in the reflected method and add to WithClass
foreach (ParameterInfo parm in m.GetParameters() )
{
if (parm.IsOut)
{
wcOp.NewParameter(parm.ParameterType.ToString(), parm.Name, parm.DefaultValue.ToString(), "out");
}
else
{
wcOp.NewParameter(parm.ParameterType.ToString(), parm.Name, parm.DefaultValue.ToString(), "in");
}
}
// Assign virtual, static, and final properties to WithClass
wcOp.IsVirtual = m.IsVirtual;
wcOp.IsStatic = m.IsStatic;
wcOp.IsFinal = m.IsFinal;
}
After we've created all the information in WithClass, we've added a method that tells WithClass to arrange its classes and relationships:
public void ArrangeAssembly()
{
myDoc.ArrangeClasses();
myDoc.ArrangeRelationships();
myDoc.RefreshWindow();
}
The ArrangeRelationships of the WithClass Document becomes more significant when we are creating relationships. We will tackle adding relationships in Part II of this 2 part discussion. The download with this article limits the # of types brought into WithClass to nineteen for demonstration purposes, but you are free to take this limitation out. Also you can use some of the WithClass 2000 trial version's add-ins to create some nice Word or HTML reports to view the reflection information in other formats.