A few months ago the patterns and practices team released the next iteration of Enterprise Library with version 4.0. This releases comes on the heels of Visual Studio 2008’s RTM and, of course, integrates nicely with VS 2008. As with previous versions many of the same application blocks can be found including Data Access, Caching, Cryptography, Exception Handling, Logging, Policy Injection, Security and Validation. New to Version 4 is The Unity Application Block. (This release can be downloaded here: http://msdn.microsoft.com/en-us/library/cc512464.aspx)
So, why should you care about Enterprise library, and what does it do for you? Essentially, Enterprise Library (EntLib) is a series of “cookie-cutter” application blocks that will enable a developer to add common functionality that has already been heavily tested and follows best practices. Think of it like this: if you were to hire a contractor to build you a house, would you expect him to figure out how to get water into your home and get waste out from scratch? Or would you expect that he would follow standard plumbing specifications and use pre-manufactured piping to control the flow of water? It’s the same with software development. Why should we constantly write a new data access layer for each project we work on? We should be able to use a common Library to do many of these repeatable and predictable tasks; that’s what EntLib gives us.
Below are 2 code examples, showing how we would get suppliers Data from the Northwind Database:
//use standard ADO.NET to get the suppliers from Northwind
SqlConnection sqlConnection = new SqlConnection ConfigurationManager.ConnectionStrings["NorthWindConnection"].ConnectionString);
sqlConnection.Open();
SqlCommand sqlCommand = new SqlCommand("SELECT SupplierID, CompanyName FROM
Suppliers", sqlConnection);
sqlCommand.CommandType = CommandType.Text;
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
DataSet supplierDataSet = new DataSet();
sqlDataAdapter.Fill(supplierDataSet);
sqlConnection.Close();
dataGridView1.DataSource = supplierDataSet.Tables[0];
Versus:
//use Enteprise Library to get the suppliers from Northwind
Database northWindDB = DatabaseFactory.CreateDatabase("NorthWindConnection");
DataSet supplierDataSet
= northWindDB.ExecuteDataSet(CommandType.Text, "SELECT SupplierID, CompanyName FROM Suppliers");
dataGridView1.DataSource = supplierDataSet.Tables[0];
The immediate advantage one recognizes is that EntLib’s code is a lot cleaner and essentially only takes 2 lines. Another advantage that is not so apparent is that EntLib gives us data abstraction. In the ADO.NET example we are working with SQL Server objects (SqlConnection, SqlCommand, etc...), so to move over to another database technology would force us to use different objects, recompile and re-deploy. In the EntLib example, notice that we never specify what type of database we are connecting to. This is because EntLib allows us to specify the database provider in the configuration file. So if we moved from SQL Server to an Oracle database, we would only have to change the connection string information and the Provider configuration from System.Data.SqlClient to System.Data.OracleClient. As we all know, not all T-SQL is created equal, so our SQL syntax might have to change, but I think you get the point. EntLib comes with 6 data providers out of the box, but if none of those meet your needs you can always write your own.
Just like version 3.0, the EntLib Configuration Manager is beautifully integrated into Visual Studio. To edit a configuration file with it, you simply right click and select “Edit Enterprise Library Configuration” in the context menu.

As mentioned before, new to EntLib is the Unity Application block. This is Microsoft’s latest tool for developing decoupled or very loosely coupled designs in your applications. This allows you to develop your components to be more flexible and to not have rigid dependencies. If your application doesn’t have many dependencies, and there is no real need for abstraction, then the Unity Application Block may be overkill for what you are trying to do. However, if your system contains several complex dependencies, some which need to be controlled and changed at runtime, then check it out. This application block is possible by using the Inversion of Control and Dependency Injection patterns. It will allow you to control the dependencies between your application’s code and utility components such as caching, validation and logging.
Another interesting fact is that while the Unity Application Block comes with EntLib, it is treated as a separate framework. It doesn’t have a dependency on EntLib’s core or configuration assemblies; in fact it’s namespace is Microsoft.Practices.Unity not Microsoft.Practices.EnterpriseLibrary.Unity.
Let’s say you have a requirement to send messages to users when some action happens, perhaps as a warning when a server is running low on disk space. You could create a utility class that takes care of this and would instantiate your class like this:
MessageUtility messageUtility = new MessageUtility();
messageUtility.SendMessage("A message..");
You then get a requirement that a message could be sent via an email or text message. So to accommodate this you abstract the message sending functionality out to an Interface called IMessage. This is fine, but we are still declaring that we are sending an EmailMessage.
IMessage message = new EmailMessage();
message.SendMessage("Some Emailed Message");
If we use the Unity framework we can register the different types of messages, Email and SMS, and then at runtime use the same container object to choose which particular message type to use. In the code below we would be controlling it with an application setting from our configuration file.
IUnityContainer container = new UnityContainer();
container.RegisterType
container.RegisterType
IMessage myMessage = container.Resolve
ConfigurationManager.AppSettings["CurrentMessageProvider"]);
myMessage.SendMessage("A message to be sent...");
You can already see the benefits, but we can make this even better by removing the container’s RegisterType calls by moving them into the configuration file. This requires us to do a little setup so let’s examine what steps are needed.
First you must register the “unity” section in your configuration file.
<configsections>
<section type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="unity">
…
</configsections>
Then you must set up Unity section and following subsections.
<unity>
<typealiases>
…
</typealiases>
<containers>
…
</containers>
</unity>
We now have 2 subsections within the unity section, Type Aliases and Containers. Type Aliases allow you to define aliases to your classes instead of defining the entire assembly, version, and public key each time. If we wanted to create aliases for our message classes we would do the following:
<!--Create a Type Alias for our EmailMessage class-->
<typealias type="RDA.Notification.EmailMessage, RDA.Notification" alias="EmailMessage">
<!--Create a Type Alias for our SMSMessage class-->
<typealias type="RDA.Notification.SMSMessage, RDA.Notification" alias="SMSMessage">
<!--Create a Type Alias for our IMessage inteface-->
<typealias type="RDA.Notification.IMessage, RDA.Notification" alias="IMessage">
Here we have defined aliases for our interface and both of our message classes. The “EmailMessage” class can be found in the RDA.Notification assembly and has the namespace of RDA.Notification.EmailMessage. We now have the ability to refer to this class in further sections (which we will) by simply referring to the alias of “EmailMessage”.
The next section is our containers element which holds a collection of container elements. Think of each one as instances of different containers that we would want to use within our application. As you might imagine a name must be assigned to each one. If we want to create a container called “MyCustomMessageContainer”, and register our message classes with it we would create the following:
<containers>
<container name="MyCustomMessageContainer">
<types>
<!-- The default message type -->
<type type="IMessage" mapto="EmailMessage">
<!— Register the SMSMessage -->
<type type="IMessage" name="SMSMessage" mapto="SMSMessage">
<!—Register the EmailMessage-->
<type type="IMessage" name="EmailMessage" mapto="EmailMessage">
</types>
</container>
</containers>
The above simply defines a container named “MyCustomMessageContainer” and defines the possible values of “SMSMessage” and “EmailMessage”. We first register “EmailMessage” as the default message type, so if no name is specified when we call the Resolve method we have a default message of email. We then define the mappings for both “SMSMessage” and “EmailMessage” using their aliases that we defined in the type alias section.
Now that our configuration is done, how do we use this? Well first we must load the container using the configuration info.
//create a new container.
UnityContainer messageContainer = new UnityContainer();
//get the unity config section
UnityConfigurationSection unitySection = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
//load the named container section
unitySection.Containers["MyCustomMessageContainer"].Configure(messageContainer);
This code really only has to be done once in an application’s lifetime, so a good place to put this might be in a factory. Now that we have our container we can use the SMS and Email classes by using their name in the registration sections:
IMessage message = messageContainer.Resolve
message.SendMessage("A message to be sent via SMS...");
IMessage message2 = messageContainer.Resolve
message2.SendMessage("A message to be sent via Email...");
IMessage messageDefault = messageContainer.Resolve
messageDefault.SendMessage("to be sent via Email because it is the default");
In the future if we need to add new message protocol or change the default, it would simply be a configuration change.
As you can see the Unity Application block is extremely powerful, and the above examples are very basic to keep things simple. Once you dive into this application block it will soon be obvious that this is just the tip of the iceberg. However it should only be used if you need the ability to dynamically change dependences on components, and have call injections. Carefully consider your situation. Although it allows for a lot of flexibility, it has a slight performance cost, and there are potential gotchas such as circular dependencies, if your architecture is not thought out.
Enterprise Library comes with a lot of great features to make developer’s lives easier and more manageable. These pluggable application blocks give you what you needed kick start your next great application. For more info about Enterprise Library and the Unity Application Block see http://www.msdn.com/ and http://www.codeplex.com/.


0 comments:
Post a Comment