I installed DotNetNuke (DNN) this weekend for the Sarasota, Florida .NET Developer Group website. Since I had DNN on my test PC, I decided to view the source code to see how it was architected. I was pleasantly pleased at how well organized the code was as well as how closely it resembled the Community Server source code. DNN is written in VB.NET and Community Server is written in C#, but the architectures are very similar.
Since they are so similar, let's walk through the source code like we did with Community Server in the following post:
Community Server Source Code - Abstract Classes, Reflection and Data Providers
One of the modules in DotNetNuke is the HTML Module. The module is responsible for displaying blocks of HTML for the portal. The usercontrol is called HtmlModule.ascx and if you look at the VB.NET in the code-behind you will see the following code snippet shown below. In Page_Load, the module instantiates a controller, of type HtmlTextController, to go out and get the HTML contents for this module based on its ModuleId. (For more information on controller, see Applying UML and Patterns: Controller GRASP Pattern - Model View Controller Design Pattern - First Object Beyond UI Layer.
The GetHtmlText function shown below has a few interesting things, many of which we talked about with the Community Server source code. DataProvider.Instance() is a Factory Method that returns the concrete Data Provider class for the HTML Module. GetHtmlText(...) is then called on this concrete class, which returns an object of IDataReader. CBO.FillObject is a helper function that will take an IDataReader and return a simple "hydrated" business object - in this case an object of type HtmlTextInfo.
Let's get back to the DataProver.Instance() factory method. DataProvider is an abstract class from which the concrete data provider will inherit. The Instance() method returns the concrete data provider:
The concrete data provider is dynamically created on the fly using reflection. The CreateProvider subroutine above calls Framework.Reflection.CreateObject (...) to create the object based on the parameter values sent to the helper class as well as the default "data" provider in the web.config file:
Below is a snippet of the actual concrete class for Sql Server that is getting the html for the HTML Module. As I mentioned above, it only returns an IDataReader. It is the CBO.FillObject(...) method that hydrates the IDataReader information into an HtmlTextInfo object.
As you can tell from the code and description above, DotNetNuke and Community Server share a lot of the same ideas. You essentially have a usercontrol who's code-behind calls a controller class. The controller class calls an Instance() factory method on an abstract data provider class that returns the concrete data provider class. Often this concrete class is instantiated using Reflection. The data call is handed off to the concrete data provider class that returns, in this case, an IDataReader. A business object is hydrated from the IDataReader class and the data reader and connection are closed. And, last, the contents are dispayed in the usercontrol.
In the near future, I will build a similar architecture using the Create a Shopping Cart object so that we can add persistence to the class.