The other day I talked about the Data Access Application Block and how you can use it in your applications to assist you with ADO.NET.
In particular, I briefly discussed this piece of code:
One of the statements worth understanding a bit better is
If you take a peek at the DAAB source code, that statement is fairly involved on the surface. It tosses you around to a number of classes and overloaded methods that could be difficult to figure out if you are new to .NET and object-oriented programming. There is some pretty cool stuff going on there, so I thought I would mimic this statement with an example that is easier to understand.
In the DAAB, Database is an abstract class. As any abstract class, you cannot create an instance of it. You can only create concrete classes that derive from Database. The DAAB currently has 2 such concrete classes: SqlDatabase and OracleDatabase.
So given this piece of knowledge, we can infer that the DatabaseFactory.CreateDatabase() static method will probably return an object of SqlDatabase or OracleDatabase which will be assigned to db. The actual concrete class will probably be created on-the-fly based on some logic (in this case the settings in the DAAB configuration file). This type of method is called a Factory Method as it defers the decision of which class to instantiate.
Let's mimic this concept by building our own classes and factory method using an example that is closely related. First our database classes. Although they are on a much simpler scale, the classes below follow the same pattern as in the DAAB. We have an abstract class, called Database, and two concrete classes, called SqlServer and Oracle, which derive from our base class of Database. I have one simple abstract method in Database, called GetManufacturer(). As an abstract method, all derived classes are required to implement this method and has been done so accordingly.
Now we need to create a Factory Method on a class that creates an instance of SqlServer or Oracle on the fly. Let's do it similar to the DAAB, but with only one class for simplicity.
The class is sealed so nobody derives from it and has a private constructor so nobody can create an instance of it. This is pretty common for these types of classes.
We have essentially two static factory methods on this class, CreateDatabase() and CreateDatabase(string databaseName), both of which return an object of type Database. If you don't specify a database, you get the default database, which is "SqlServer". This is sort of like the DAAB, but the DAAB looks in the configuration file to find the default database. In this case, I just hardcoded it for simplicity.
Now the cool stuff is in the second method, CreateDatabase(string databaseName). The databaseName parameter is the name of the class type we want to create on-the-fly. In our case, it either has to be SqlServer or Oracle, the two concrete classes we created that derive from Database.
The rest is simple reflection similar to how it is done in the DAAB. The comments above really tell it all. We find the type requested in databaseName (SqlServer or Oracle), get its default constructor, and then invoke its default constructor which passes back an instance of the type. We then just cast the object to type Database and return it back to the calling program.
Here is code you can run to test all our classes:
Hopefully the above code will illuminate what is going on in the DAAB when you make a call to DatabaseFactory.CreateDatabase(). Although we are doing it on a much simpler scale, it is the same technique and one you can use in your applications.