Archive

Posts Tagged ‘Enterprise Library’

Caching Application Block and database backing store

February 6, 2009 2 comments

Caching can help to overcome some of the challenges associated with enterprise-scale distributed web applications:

  • Performance – Caching improves application performance by storing relevant data as close as possible to the data consumer. This avoids repetitive data creation, processing and transportation
  • Scalability – Storing information in a cache helps save resources and increases scalability as the demands on the application increase
  • Availability – By storing data in a local cache, the application may be able to survive system failures such as network latency, web service problems, and hardware failures

Out of the box ASP.NET provides three primary forms of caching:

  • Page Level output caching – A copy of the HTML that was sent in response to a request is kept in memory and subsequent request are then sent the cached output until the cache expires. This can result in large performance gains as sending the cached output is always very fast and fairly constant
  • User Control level output caching (fragment caching) – Page level output caching may not be feasible in cases where certain parts of the page are customized for the user. Yet, there may be other parts of the page e.g. menus and layout elements which are common to the entire application. The cached controls can be configured to vary based on some set property or any of the variations supported by page level caching. All pages using the same controls share the same cached entries for these controls.
  • And the Cache API – The real power of caching is exposed via the Cache object. ASP.NET includes an easy-to-use caching mechanism that can be used to store objects in memory that require a lot of server resources. The .NET Framework includes the ASP.NET cache in the System.Web namespace which can be accessed through the System.Web.HttpContext.Cache object. WinForm applications can also make use of this Cache object by referencing the System.Web assembly and can access it through the System.Web.HttpRuntime.Cache object. Instances are private to each application and the lifetime is tied to the corresponding application.

By using the Caching Application Block we can write a consistent form of code to implement caching in any application component, be it the web UI, a Windows service, a WinForm desktop application, or a web service. The Caching Application Block is optimized for performance and is both thread safe and exception safe.

The Caching Application Block works with ASP.NET cache and provides a number of features that are not available to the ASP.NET cache such as:

  • The ability to use a persistent backing store – both isolated storage and database backing store
  • The ability to encrypt a cache item’s data – this works only when using a persistent backing store
  • Multiple methods of setting expiration times – absolute time, sliding time, extended time format, file dependency, or never expires
  • The core settings are described in configuration files and can be changed without recompilation of the project
  • Can be extended to create your own expiration policies and storage mechanisms

To use the Caching Application Block you need to add references of the following assemblies to your project:

  • Microsoft.Practices.EnterpriseLibrary.Common
  • Microsoft.Practices.EnterpriseLibrary.Caching

The following namespaces need to  be included in the classes that use the Caching Block:

  • Microsoft.Practices.EnterpriseLibrary.Caching
  • Microsoft.Practices.EnterpriseLibrary.Caching.Expirations
  • Microsoft.Practices.EnterpriseLibrary.Common

If there is a requirement for a persistent backing store then the data access block needs to be included:

  • Microsoft.Practices.EnterpriseLibrary.Data
  • Microsoft.Practices.EnterpriseLibrary.Caching.database

If  there is a requirement to encrypt data in the persistent backing store then the encryption block needs to be included:

  • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography

Configuration the Cache Block

In Memory Cache

<configSections> 

         <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 

</configSections> 

<cachingConfiguration> 

          <cacheManagers> 

                    <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="10" numberToRemoveWhenScavenging="5" backingStoreName="Null Storage" name="Prices" /> 

          </cacheManagers> 

          <backingStores> 

                    <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations .NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Null Storage" /> 

          </backingStores> 

</cachingConfiguration> 

Cache Using Backing Store

Use the database backing store provider when deploying your application on a web farm on multiple computers or on multiple processes on the same machine scenario. To use the database backing store you need to first create the cache database on SQL Server. The script to do this can be found in <Enterprise Library Source Dir>\App Blocks\Src\Caching\Database\Scripts.

<configSections> 

         <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 

         <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 

</configSections> 

<dataConfiguration defaultDatabase="Northwind" /> 

<connectionStrings> 

         <add name="CacheDSN" connectionString="Data Source=(local);Initial Catalog=Caching;Integrated Security=True;User Instance=False" providerName="System.Data.SqlClient" /> 

        <add name="Northwind" connectionString="Data Source=(local);Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /> 

</connectionStrings> 

<cachingConfiguration defaultCacheManager="Customers"> 

         <cacheManagers> 

                 <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="11000" numberToRemoveWhenScavenging="10" backingStoreName="DataStorage" name="Customers" /> 

         </cacheManagers> 

         <backingStores> 

                 <add databaseInstanceName="CacheDSN" partitionName="MyFirstCacheApp" encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.Database.DataBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="DataStorage" /> 

         </backingStores> 

</cachingConfiguration> 

Cache Application Block Class Reference

CacheFactory Class – The CacheFactory uses the supplied configuration information to determine the type of cache object to construct

GetCacheManager – The GetCacheManager method returns a CacheManager object determined by the configuration information

ICacheManager myCache = CacheFactory.GetCacheManager(); //uses the default cache specified in configuration 

ICacheManager myCustomerCache = CacheManager.GetCacheManager("Customers"); //overload creates the name cache CustomerData 

CacheManager Class – The CacheManger class acts as the interface between the application and the rest of the caching block. It provides all the methods required to manage the applications

GetData – The GetData method returns an object from the cache containing the data that matches the supplied ID. If the data does not exist or if it has expired Null is returned

Customer oCustomer = myCustomerCache.GetData("CustomerID"); 

Add – The Add method will add an item to the cache

myCustomerCache.Add("CustomerID", oCustomer); 

myCustomerCache.Add("CustomerID", oCustomer, scavengingPriority, refreshAction, cacheExpirations); 

Contains – The Contains method returns true if the item exists in the cache

bool dataExists = myCustomerCache.Contains("CustomerID"); 

Remove – The Remove method will delete an item from the cache

myCustomerCache.Remove("CustomerID"); 

Flush – The Flush method removes all items from the cache. If an error occurs during the flush the cache is left unchanged

myCustomerCache.Flush(); 

Monitoring Your Cache Performance

Monitoring your cache usage and performance can help you understand whether your cache is performing as expected and helps you to fine tune your cache solution. You can use the Windows performance monitor application (Perfmon) to view and analyze your cache performance data when it is not delivering the expected performance.

To monitor cache performance

  • Monitor the Cache Insert and Cache Retrieve Times under different cache loads (for example, number of items and size of cache) to identify where your performance problem is coming from. These two performance counters should be as low as possible for your cache to be more responsive to the application. You should note that the cache insert time and retrieve time should be constant regardless of the number of items in cache.
  • Check your Cache Hit/Miss ratio. A cache hit occurs when you request an item from the cache and that item is available and returned to you. A cache miss occurs when you request an item from the cache and that item is not available. If this is low, it indicates that items are rarely in cache when you need them. Possible causes for this include:
    • Your cache loading technique is not effective.
    • Your maximum allowed cache size is too small, causing frequent scavenging operations, which results in cached items being removed to free up memory.
  • Check your Cache Turnover rate. The cache turnover rate refers to the number of insertions and deletions of items from the cache per second. If this is high, it indicates that items are inserted and removed from cache at a high rate. Possible causes for this include:
    • Your maximum allowed cache size is too small, causing frequent scavenging operations which result in cached items being removed to free up memory.
    • Faulty application design, resulting in improper use of the cache.
  • Additionally you can also monitor the Cache Entries and Cache Size counters. Although the Cache Entries counter does not provide enough information regarding your cache performance it can be used with other counters to provide valuable information.

Regular monitoring of your cache should highlight any changes in data use and any bottlenecks that these might introduce. This is the main management task associated with the post-deployment phase of using a caching system.

Synchronizing Caches in a Server Farm

A common problem for distributed applications developers is how you synchronize cached data between all servers in the farm. Generally speaking, if you have a situation in which your cache needs to be synchronized in your server farm, it almost always means that your original design is faulty. You should design your application with clustering in mind and avoid such situations in the first place.

You can configure the Cache Application Block to share the backing store between servers in a web farm. All machines in the farm can have the same cache instance and partition and can read/write to the store. But the in-memory version of the cache is always unique to each server in the farm.

However, if you have one of those rare situations where such synchronization is absolutely required, you should use file dependencies to invalidate the cache when the information in the main data store changes.

To create file dependencies for cache synchronization

  • Create a database trigger that is activated when a record in your data store is changed.
  • Implement this trigger to create an empty file in the file system to be used for notification. This file should be placed either on the computer running SQL Server, a Storage Area Network (SAN), or another central server.
  • Use Application Center replication services to activate a service that copies the file from the central server to all disks in the server farm.
  • Make the creation of the file on each server trigger a dependency event to expire the cached item in the ASP.NET cache on each of the servers in the farm.

NOTE: because replicating a file across the server farm can take time, it is inefficient in cases where the cached data changes every few seconds.

The Caching Application Block should not be used if:

  • The ASP.NET cache provides all the caching functionality that the application requires
  • If security is an issue. While the persistent cache allows data to be encrypted there is no support to encrypt the in memory cache. If a malicious user could gain access to the system they can potentially retrieve cached data. Do not store sensitive information such as passwords and credit numbers in the cache if this is an issue for the application.
  • If multiple applications need to share the cache or the cache and application need to reside on separate systems.
  • The cache should ideally be used to store data that is either expensive to create or expensive to transport and that is at least semi-static in nature. It is generally not a good idea to cache transactional data

    Unity – Dependency Injection and Inversion of Control Container

    September 8, 2008 10 comments

    The Dependency Injection Pattern
    Dependency injection is a programming technique to reduce component coupling. Dependency injection is also commonly known as “inversion of control” or IoC or sometimes as The Hollywood Principle – "Don’t call us, we’ll call you”. The goal of dependency injection is to separate the concerns of how a dependency is obtained from the core concerns of a boundary. This improves reusability by enabling components to be supplied with dependencies which may vary depending on context.

    The Old Way
    Following is an example of how you might write code if not using dependency injection

    public class WebApp { public WebApp() { quotes = new StockQuotes(); authenticator = new Authenticator(); database = new Database(); logger = new Logger(); errorHandler = new ErrorHandler(); } }

    Problem

    • What about the child objects?
    • How does the StockQuotes find the Logger?
    • How does the Authenticator find the database?
    • Suppose you want to use a TestingLogger instead? Or a MockDatabase?

    Service Locator pattern attempts to solve some of the problems mentioned above by providing a dictionary of objects. The objects are all stored in this dictionary and the Get method simply returns the object to the caller.

    Service Locator Example

    public interface ILocator { TObject Get<TObject>(); } public class MyLocator : ILocator { protected Dictionary<Type, object> dict = new Dictionary<Type,object>(); public MyLocator() { dict.Add(typeof(ILogger), new Logger()); dict.Add(typeof(IErrorHandler), new ErrorHandler(this)); dict.Add(typeof(IQuotes), new StockQuotes(this)); dict.Add(typeof(IDatabase), new Database(this)); dict.Add(typeof(IAuthenticator), new Authenticator(this)); dict.Add(typeof(WebApp), new WebApp(this)); } } public class StockQuotes { public StockQuotes(ILocator locator) { errorHandler = locator.Get<IErrorHandler>(); logger = locator.Get<ILogger>(); } }

    Pros

    • Classes are decoupled from explicit implementation types
    • Easy to externalize the config

    Cons

    • Everyone takes a dependency on the ILocator
    • Hard to store constants and other useful primitives
    • Creation order is still a problem

    Dependency Injection Containers
    The dependency injection container is a component responsible for assigning dependencies to a recipient component. Containers are generally implemented using the Factory Pattern to allow creation of the recipient and dependency components. Containers are often implemented to allow existing objects to be registered for use as a dependency, or to create new instances when required. Using a dependency injection container with our StockQuotes example provides the following benefits:

    • Gets rid of the dependency on the ILocator
    • Object is no longer responsible for finding its dependencies
    • The container does it for you

    In a nutshell, dependency injection just means that a given class or system is no longer responsible for instantiating their own dependencies. In this case “Inversion of Control” refers to moving the responsibility for locating and attaching dependency objects to another class or a DI tool. That might not sound that terribly profound, but it opens the door for a lot of interesting scenarios.
    Benefits of Dependency Injection:

    • Dependency Injection is an important pattern for creating classes that are easier to unit test in isolation
    • Promotes loose coupling between classes and subsystems
    • Adds potential flexibility to a codebase for future changes
    • Can enable better code reuse

    Unity Application Block
    Unity Application Block is a lightweight Inversion of Control container which supports constructor, property and method call injection. Unity sits on top of another framework called ObjectBuilder, but is different from the ObjectBuilder which has been a part of Enterprise Library 3.1 and earlier. Unity is based on v2 of the Objectbuilder and has been optimized for performance quite a bit. Unity is available both as a standalone and part of Enterprise Library 4.0 on codeplex at http://www.codeplex.com/unity and http://www.codeplex.com/entlib. Unity 1.1 is not part of Enterprise Library 4.0 but the good thing about it is that it will update the Unity dlls/libraries in Enterprise Library 4.0 installed folder to 1.1 during installation.

    The Unity Application Block includes the following features:

    • It provides a mechanism for building (or assembling) instances of objects, which may contain other dependent object instances.
    • It exposes RegisterType methods that support configuring the container with type mappings and objects (including singleton instances) and Resolve methods that return instances of built objects that can contain any dependent objects.
    • It provides inversion of control (IoC) functionality by allowing injection of preconfigured objects into classes built by the application block. Developers can specify an interface or class type in the constructor (constructor injection), or apply attributes to properties and methods to initiate property injection and method call injection.
    • It supports a hierarchy for containers. A container may have child container(s), allowing object location queries to pass from the child out through the parent container(s).
    • It can read configuration information from standard configuration systems, such as XML files, and use it to configure the container.
    • It makes no demands on the object class definition. There is no requirement to apply attributes to classes (except when using property or method call injection), and there are no limitations on the class declaration.
    • It supports custom container extensions that developers can implement; for example, methods to allow additional object construction and container features such as caching.

    Unity has no dependency on Enterprise Library core and can be used without having to install Enterprise Library on the host system. To use Unity in your application you need to add reference to the following dlls in your project
        Microsoft.Practices.ObjectBuilder2
        Microsoft.Practices.Unity

    The Unity container can be configured through configuration files or you can use code to register dependencies dynamically at run time. To use Unity with configuration files you need to add reference to the following dll
        Microsoft.Practices.Unity.Configuration

    Steps when using Dependency Injection

    • Write your objects the way you want
    • Setup the container
    • Ask the container for objects
    • The container creates objects for you and fulfills dependencies

    Setup the container
    The ideal place to setup the Unity container for ASP.NET applications is in the Application_Start method of the global.asax file. We would like to have a persistent container that hold it’s state during the execution of the application. The right place to put this is in the Global.asax file as a property of the current application.

    We create a simple interface for the container property so that we can access our container using this interface

    public interface IContainerAccessor { IUnityContainer Container { get; } }

    class in the Global.asax file:

    private static UnityContainer _container; public static UnityContainer Container { get { return _container; } set { _container = value; } } protected void Application_Start(object sender, EventArgs e) { BuildContainer(); } protected void Application_End(object sender, EventArgs e) { CleanUp(); } private static void BuildContainer() { IUnityContainer container = new UnityContainer(); //TODO: Register the relevant types for the container here through classes or configuration Container = container; } private static void CleanUp() { if (Container != null) { Container.Dispose(); } }

    The BuildContainer method is where we will setup our container and register our types for dependency injection. The RegisterType<TFrom, TTo>() method tells Unity that whenever someone asks for a dependency on TFrom give them Tto. In the example code below the statement container.RegisterType<ILogger, EventLogLogger>() tells Unity that whenever someone has a dependency on type ILogger go ahead and create an object of type EventLogLogger.

    There are a couple of different flavors of Dependency Injection

    • Constructor Injection – Attach the dependencies through a constructor function at object creation
    • Setter Injection – Attach the dependencies through setter properties
    • Service Locator – Use a well known class that knows how to retrieve and create dependencies. Not technically DI, but this is what most DI/IoC container tools really do

    Constructor Injection

    public interface ILogger { void LogEvent(string message); } public class FileLogger : ILogger { public void LogEvent(string message) { ... } } public class EventLogLogger : ILogger { public void LogEvent(string message) { ... } } public class StockQuotes { private Ilogger _logger; public class StockQuotes(ILogger logger) { _logger = logger; } } UnityContainer container = new UnityContainer(); ... contianer.RegisterType<ILogger, EventLogLogger>(); StockQuotes quotes = container.Resolve<StockQuotes>();

    If a class that developers instantiate using the Resolve method of the Unity container has a constructor that defines one or more dependencies on other classes, the Unity container will automatically create the dependent object instance specified in parameters of the constructor. In the above example StockQuotes has a dependency on ILogger. When we create an instance of the StockQuotes class using the Resolve method of the Unity container, Unity will automatically create an instance of EventLogLogger and pass it to the constructor of StockQuotes class.

    The benefit of using constructor injection is that the constructor function now explicitly declares the dependencies of a class. Constructor injection is often recommended as it eliminates chatty calls to the object and creates a valid object in as few steps as possible.

    Setter Injection

    public class OracleDatabase : IDatabase { Public void ExecuteQuery(string query) { ... } } public class SqlDatabase : IDatabase { public void ExecuteQuery(string query) { ... } } public class Authenticator { private IDatabase _database; [Dependency] public IDatabase DB { get{return _database;} set{_database = value;} } } UnityContainer container = new UnityContainer(); ... contianer.RegisterType<IDatabase, SqlDatabase>(); Authenticator auth = container.Resolve<Authenticator>();

    To force dependency injection of the dependent object, developers must apply the [Dependency] attribute to the property declaration. Many would argue that setter injection is really useful when legacy code needs to be upgraded and provides a smooth transition from legacy code to the new model. Making sure that any new code that depends on undesirable legacy code uses Dependency Injection leaves an easier migration path to eliminate the legacy code later with all new code. 

    As a service locator

    UnityContainer container = new UnityContainer(); contianer.RegisterType<ILogger, NullLogger>(); … ILogger logger = container.Resolve<ILogger>();

    Here we are just telling unity to give us the ILogger interface which is already registered with the container. Using the container in this manner makes it a service locator.

    Unity Dependency injection provides a number of ways to configure the container. As described above you use the RegisterType method to inform the container about dependencies. But Unity can also manage the object lifetime e.g.

    Dependencies as singleton

    UnityContainer container = new UnityContainer(); container.RegisterType<Database, SqlDatabase>(new ContainerControlledLifetimeManager());

    The above code  tells Unity that whenever someone asks for type Database give them type SqlDatabase and return the same object every time instead of creating a new one for each dependency.

    Named Instance

    UnityContainer container = new UnityContainer(); contianer.RegisterType<Database, SqlDatabase>("SQL"); container.RegisterType<Database, OracleDatabase>("Oracle"); IEnumerable<Database> databases = container.ResolveAll<Database>(); Database database = container.Resolve<Database>("SQL");

    Named instance allows you to configure Unity with multiple dependencies for the same type but assign them different names. Thi s allows you to do fancy stuff where you want a default type mapping but also want to override the mapping by providing a name during object creation.

    Registering an existing object instance
    So far all the examples above show how a type can be registered with Unity and the Unity container creates the object for you whenever requested. But what if you already have the object created and want to register this object in Unity.

    UnityContainer container = new UnityContainer(); contianer,RegisterInstance<Database>(new SqlDatabase()); contianer.RegisterInstance<Database>("Oracle", new OracleDatabase()); Database database = container.Resolve<Database>(); Database oracleDatabase = container.Resolve<Database>("Oracle");

    When using RegisterIntance Unity will automatically make the objects singletons.

    Configuring Unity via config file
    The Unity container can be configured through configuration files. To use Unity with configuration files you need to add reference to the following dll
        Microsoft.Practices.Unity.Configuration

    Use following code to read the container setup from configuration file:

    UnityContainer container = new UnityContainer(); UnityConfgurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); Section.Containers.Default.GetConfigCommand().Configure(); ILogger logger = container.Resolve<ILogger>();

    .config file:

    <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> </configSections> <unity> <typeAliases> <!-- Lifetime manager types --> <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" /> <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,Microsoft.Practices.Unity" /> </typeAliases> <containers> <container> <types> <type type="ConsoleApplication1.Database, ConsoleApplication1" mapTo="ConsoleApplication1.SqlDatabase, ConsoleApplication1" lifetime="Singleton" /> <type type="ConsoleApplication1.ILogger, ConsoleApplication1" mapTo="ConsoleApplication1.EvnetLogLogger, ConsoleApplication1" lifetime="Singleton" /> </types> </container> </containers> </unity>

    Nested Containers
    Unity supports nested containers, which allows the parent container to create child containers. This provides the ability to override parent type mappings with child type mappings. Parent-Child relationship between Unity containers. What this means is that the parent-child relationship between Unity containers will search the child container to the resolve the type mapping, and if not found, will navigate up to the parent container to resolve the type.

    UnityContainer parentContainer = new UnityContainer(); IUnityContainer childContainer1 = parentContainer.CreateChildContainer(); IUnityContainer childContainer2 = parentContainer.CreateChildContainer(); parentContainer.RegisterType<ILogger, FileLogger>(new ContainerControlledLifetimeManager()); childContainer1.RegisterType<ILogger, EventLogLogger>(new ContainerControlledLifetimeManager()); ILogger logger = childContainer2.Resolve<ILogger>(); // should return FileLogger from parentContainer ILogger logger2 = childContainer1.Resolve<ILogger>(); //should return EventLogLogger from childContainer1

    While registering types with Unity there is a certain risk of introducing unintentional circular references, which are not easy to detect or prevent.
    For example, the following code shows two classes that reference each other in their constructors.

    public class Class1 { public Class1(Class2 test2) { ... } } public class Class2 { public Class2(Class1 test1) { ... } }

    It is the responsibility of the developer to prevent this type of error by ensuring that the members of classes they use with dependency injection do not contain circular references.

    References

    Dependency Injection: Factory vs Container – Unity

    June 30, 2008 Leave a comment

    As application size and complexity increase it becomes more and more difficult to reuse existing components and integrating these components to form an interconnected architecture because of the dependencies of the components. One way to reduce dependencies is by using Dependency Injection, which allows you to inject objects into a class, rather than relying on the class to create the object itself.

    Dependency Injection refers to the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The basic value Dependency Injection brings to enterprise systems is decoupling. They promote programming to interfaces and isolate you from the creation process of the collaborators, letting you to concentrate on what you need to deliver while improving testing.

    The dependency injection approach offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used either pragmatically or via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a mock implementation of a service into the object being tested.

    Dependency injection helps in solving the following

  • You want to decouple your classes from their dependencies so that these dependencies can be replaced or updated with minimal or no changes to your classes source code.
  • You want to be able to write classes that depend on classes whose concrete implementation is not known at compile time.
  • You want to be able to test your classes in isolation, without using the dependencies.
  • You want to decouple your classes from being responsible for locating and managing the lifetime of dependencies.

    The factory pattern described as "To construct and instantiate a set of related objects without specifying their concrete objects." is one common way to implement Dependency Injection. When a component creates an instance of another class, it encapsulates the object creation logic within the component. Any other class that requires an instance of the created class must also duplicate the object creation logic as it may not be reusable outside the component.

    Object most often need to be instantiated in a coordinated fashion, usually because of certain dependencies or other requirements. For example, when creating an instance of XmlValidatingReader in client code, an XmlSchemaCollection object is frequently populated with the relevant schemas for use when validating the XmlValidatingReader object. This is an example of needing to not only create an instance of a class, but also to configure it after creation and before it can be used.

    Another example of a factory pattern is to create a static method whose purpose is to return an instance of a class. For example, the Create method of WebRequest takes in either a string or Uri instance, and returns a new instance of a class derived from WebRequest.

    Factories allow for an application to wire together objects and components without exposing too much information about how the components fit together or what dependencies each component might have. Instead of spreading complex creating code around an application, factories allow for that code to be housed in a central location, thereby facilitating reuse throughout the application.

    Client code then calls creating methods on the factory, with the factory returning complete instances of the requested classes. Encapsulation is preserved, and the client is effectively decoupled from any sort of plumbing required to create or configure the object instance.

    Benefits of Factory Pattern

  • Factories allow for an application to wire together objects and components without exposing too much information about how the components fit together or what dependencies each component might have.
  • Instead of spreading complex creating code around an application, factories allow for that code to be housed in a central location, thereby facilitating reuse throughout the application.
  • Client code calls creating methods on the factory, with the factory returning complete instances of the requested classes. Encapsulation is preserved, and the client is effectively decoupled from any sort of plumbing required to create or configure the object instance.

    Drawbacks of factory pattern

  • While a factory implementation can be quite valuable for a certain application, most of the time, it is not reusable across other applications. Frequently all of the available creation options are hardcoded into the factory implementation, making the factory itself non-extensible. Most of the time the class calling the factories’ creation methods must know which subclass of the factory to create.
  • All dependencies for an object that is created using a factory are known to the factory at compile time. At run time there is no way to insert or alter the manner in which objects are created, or which dependencies are populated. This all must happen at design time, or at least require a recompile. For example, if a factory is creating instances of class Foo and instances of class Foo require an instance of class Bar, then the factory must know how to retrieve an instance of the Bar class. The factory could create a new instance, or even make a call to another factory.
  • Since factories are custom to each individual implementation, there can be a significant level of cross-cutting infrastructure that is held captive inside a particular factory. Take my example of a factory dynamically substituting a proxy object for a real object. That is an example of a piece of infrastructure, namely the wrapping of simple objects for deployment over a distributed wire, that is completely encapsulated inside that particular factory. If another object needs to be altered in a similar manner, the logic to do so is hidden inside a factory, and would have to be repeated for the other object. Once this functionality is desired outside of the original application, the problem now becomes how to reuse such functionality while still maintaining the existing factory concept.
  • Factories rely on well-defined interfaces to achieve polymorphism. In order for a factory implementation to be able to dynamically create different concrete subclass instances, there must be a common base class or shared interface implemented by all classes that the factory will create. Interfaces decouple the construction of the object from the specific implementation of the interface. The dilemma that arises now is how you can accomplish this decoupling without being forced to create an interface for everything.

    A container is a compartment that houses some sort of abstraction within its walls. Typically, responsibility for object management is taken over by whatever container is being used to manage those objects. However, containers can also take over instantiations, configuration, as well as the application of container-specific services to objects.

    Containers provide the ability to wrap vanilla objects with a wealth of other services. This allows the objects to remain ignorant about certain infrastructure and plumbing details, like transactionality and role-based security. Oftentimes, the client code does not need to be aware of the container, so there is no real dependency on the container itself. Containers be configured declaratively, meaning they can be configured via some external means, XML files, property files, or .NET-based attributes.

    Dependency Injection is a worthwhile concept to explore for use within applications that you develop. Not only can it reduce coupling between components, but it also saves you from writing boilerplate factory creation code over and over again. Unity is an example of a framework that provides a ready to use Dependency Injection container. Of course all this also means that there is added complexity to the source code; therefore, it is harder to understand.

    Microsoft Patterns and Practices team had been developing Enterprise Library to enable the use of general patterns and practices for .NET platform, which has great pluggable application blocks such as Logging and Validation application blocks. One of them is the Dependency Injection Application Block; but folks thought it should be named differently from the other application blocks, and came with the fancy name Unity.

    Unity exposes Register methods that support configuring the container with mappings and objects (including singleton instances), and Resolve methods to return instances of built objects that contain any dependent objects. Unity sits on top of another framework called ObjectBuilder which has been a part of enterprise library for quite some time. Unity however is based on v2.0 of the object builder which has been tweaked, refactored and optimized for performance. Unity is available as both a standalone download or part of the enterprise library and can be downloaded from http://www.codeplex.com/unity or http://www.codeplex.com/entlib.

    Unity supports the following forms of dependency injection:

  • Constructor injection – parameters of the objects constructor method are used to inject it with its dependencies.
  • Setter injection – object simply provides a property that can hold a reference to that type of service; and when the object is created a reference to an implementation of that type of service will automatically be injected into that property – by an external mechanism.

    David Hayden has done some great screencasts on Enterprise Library and Unity at http://www.pnpguidance.net/ be sure the check them out for furhter readings on dependency injection using Unity Applicaiton Block.

    Technorati Tags: ,

  • Using Validation Application Block in ASP.NET

    May 19, 2008 3 comments

    Any web page which requires input from the user simply cant allow just any data to be entered because the data might be too long, missing or incorrect. We need to validate the data entered by the users in a number of ways; for example, First Name and Last Name might be required fields and Date of Birth cannot be greater than the current date etc. We can very well use the client side validators provided by ASP.NET like RequiredFieldValidator, CompareValidator or RegularExpressionValidtor but is that really enough? What if JavaScript is disabled by the client? What if we need to validate our business objects? It is often important to validate data several times within the same application. For example, you may need to validate object instances that you:

    • Generate in separate tiers or components of your application
    • Retrieve from a cache, a repository, or a third-party data access layer
    • Receive from a Web Service as an object instance or a set of property values
    • Reconstruct from existing values, perhaps populating them by copying properties from a similar object or using values retrieved from a database

    Enter the Enterprise Library with its Validation Application Block.

    The Validation Application Block is designed to address the most common tasks developers face when they must validate input either from a user or another system. The Validation Application Block provides a comprehensive series of validation components that you can apply through configuration, or through attributes applied directly to classes, class members, plus UI controls for use in both ASP.NET and Windows Forms applications.

    One of the major advantages with Validation Application Block is that you can define rule sets within your application configuration file, with each rule set defining the types of validation to undertake and the individual parameters for that validation process. This means that administrators can quickly and easily change the validation rules and parameters without requiring any changes to the existing code – avoiding the risk of code errors, recompilation issues, and application downtime.

    The Validation Application Block is designed to do the following:

    • Encapsulate the logic used to perform the most common validation tasks into minimal application code.
    • Relieve developers of the requirement to write duplicate code and custom code for common validation tasks.
    • Allow validation rules to be changed after the application has been deployed, and ensure that changes happen simultaneously and consistently.

    There are four ways that you can associate validators with your types:

    • You can use configuration.
    • You can use attributes.
    • You can use a combination of configuration and attributes.
    • You can use self validation, which means that you include validation logic within the object you want to validate.

    The Validation Application Block contains a wide range of validators that you can use to check almost any type of property or value. The built-in validators include:

    • Range Validators –
      • Range Validator – checks that a value falls within a specified range. The range may be either closed, which means it has both a lower and an upper bound specified, or open, which means that it only has one bound specified. The Range Validator can be used with any type that implements the IComparable interface. This includes all numeric types and strings. While it is possible, in code, to use this validator with DateTime types, the Date Time Range Validator may be a better choice because it allows you to take advantage of attributes and configuration.
      • Date Time Range Validator – checks that a DateTime object falls within the specified range.
      • String Length Validator – checks that the length of the string is within the specified range. The range may include or exclude the endpoints by omitting the lower or upper bound.
    • String Validators
      • Contains Characters Validator – checks that an arbitrary string, such as a string entered by a user in a Web form, contains any or all of the characters that are specified by the CharacterSet property.
      • Regular Expression Validator – checks that the value matches the pattern specified by a regular expression.
      • Type Conversion Validator – checks that a string can be converted to a specific type. For example, the validator can check that "6.32" can be converted to a Double type or that "2007-02-09" can be converted to a DateTime type.
    • Set Validators
      • Domain Validator – checks that a value is one of the specified values in a specified set. For example, it can check that a name is "Tom," "Dick," "Harry," or "George" or that an integer is 2, 3, 5, 7, or 11. If the set only contains one value, you can use this validator to check for equality.
      • Enum Conversion Validator – checks that a string can be converted to a value in a specified enum type. For example, it can check that "Blue" can be converted to a value in the Color enumeration.
    • Comparison Validators
      • Property Comparison Validator – compares the value to be checked with the value of a property. For example, a n AuctionItem object, the current bid is greater than or equal to the minimum bid.
      • Relative Date Time Validator – checks that the DateTime value falls within a specified range using relative times and dates.
    • Object Validators
      • Not Null Validator – checks that the value is not null.
      • Object Validator – causes validation to occur on an object reference. All validators defined for the object’s type will be invoked, just as if the Validation.Validate method had been called on the object. If the object you want to validate is null, the validation is ignored. If the reference is to an instance of a type that is not compatible with the configured target’s type, the validation fails. This validator is helpful for validating tree-structured data.
      • Object Collection Validator – checks that the object is a collection of the specified type and then invokes validation on each element of the collection. If the object you want to validate is null, the validation is ignored. If the object you want to validate is not a collection, then the validation fails and the rule set is not applied. If there are elements in the collection that are of a different type than the one you specified for the object, then the validation for these elements fails but this does not affect validation for the other elements.

    The Validation Application Block also provides the following composite validators which allow you to combine other validators by nesting them within this type of validator to create complex validation rules.

    • And Composite Validator – requires that all the validators that make up the composite validator be true. For example, you can use the And Composite Validator to require that the Not Null Validator AND the Date Time Range Validator be True. Because the Validation Application Block’s default behavior is to AND validators, you only need this validator to implement complex logic.
    • Or Composite Validator – requires that at least one of the validators that make up the composite validator be True. For example, you can use the Or Composite Validator to require that the Not Null Validator OR the Date Time Range Validator be True.

    Each validator also has a Negated property, which reverses the operation of the validator so that it returns False if the value is valid, and True if not. This is useful when you combine validators using the And Composite Validator and the Or Composite Validator.

    Assume that our customer entity is as follows and we want to validate the fields within this object for some business rules. For example, Postal Code format nnnnn[-nnnn] etc.

    public class Customer { public string Name { get; set; } public string Address { get; set; } public string City { get; set; } public string PostalCode { get; set; } public int EmployeeCount { get; set; } public DateTime LastReportDate{ get; set; } }

    The first step when using the Validation Application Block is to create rule set(s) for our type / object. To create a rule set for an object, you must first create and compile that assembly. Once you have a target object class, open the configuration file for your application in the Configuration Editor integrated within Visual Studio by right-clicking on the Web.config file in the Solution Explorer window and select Edit Enterprise Library Configuration.

    In the configuration editor, right click on the application node and select New, then click Validation Application Block to add the Validation Application Block to your application. Then right-click on the new Validation Application Block node, select New, and click Type. In the Type Selector dialog, click the Load an assembly button and navigate to the folder containing your target object. Click Open to load this assembly. Find your target assembly in the list and select the target class to which you want to attach a rule set.

    Click OK, and the class appears in the configuration under the Validation Application Block node. Now you are ready to create the rule set.

    Right-click on the new target object node in the configuration editor, select New, and click Rule Set. Change the name of the rule set as required – you will use the name in your code so you should specify a name that will help you to read and debug your code, especially if you define more than one rule set.

    The next stage is to select the members of the target object that you want to validate. Right-click on the new rule set node, select New, and click Choose Members to display a dialog containing all the public members of the target object. Select the required members and click OK to close the dialog and add these members to the rule set.

    You now have a hierarchy that contains the list of members to which you will add validators. For each target object member, right-click on it, select New, and click the type of validator you want to add. As you add each one, use the Properties window in Visual Studio to set the properties you require for each validator.

    For example, the CompanyAddress property has a String Length Validator attached with the following properties set:

    <validation> <type assemblyName="TestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="TestApp.Customer"> <ruleset name="ExampleRuleSet"> <properties> <property name="Name" > <validator lowerBound="5" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Customer address must be between 5 and 100 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerAddressValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="Address"> <validator lowerBound="5" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Customer address must be between 5 and 100 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerAddressValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="City"> <validator lowerBound="2" lowerBoundType="Inclusive" upperBound="30" upperBoundType="Inclusive" negated="false" messageTemplate="City name must be between 2 and 30 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerCityValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="PostalCode"> <validator pattern="\d{5}(-\d{4})?" options="None" patternResourceName="" patternResourceType="" messageTemplate="Postal code must be in the form nnnnn[-nnnn]" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerPostalCodeValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RegexValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Regex Validator"/> </property> <property name="EmployeeCount"> <validator lowerBound="1" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Employee count must be between 1 and 100" messageTemplateResourceName="" messageTemplateResourceType="" tag="EmployeeCountValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RangeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Range Validator"/> </property> <property name="LastReportDate"> <validator lowerBound="2007-01-01" lowerBoundType="Inclusive" upperBound="2008-03-28" upperBoundType="Inclusive" negated="false" messageTemplate="Report Date must be between 1st Jan and 31st Dec 2007" messageTemplateResourceName="" messageTemplateResourceType="" tag="LastReportDateValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.DateTimeRangeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Date Range Validator"/> </property> </properties> </ruleset> </type> </validation>

    ASP.NET integration uses a class named PropertyProxyValidator, which implements a control that you can use within an ASP.NET Web page to perform UI validation. This control inherits from the ASP.NET validation control base class named BaseValidator, and is therefore effectively an ASP.NET validation control.

    The BaseValidator class exposes properties such as ControlToValidate, Display (None, Static, Dynamic), EnableClientScript, Enabled, IsValid, SetFocusOnError, and ValidationGroup. The PropertyProxyValidator class also exposes the Validate method, which you can use to initiate validation of specific validators if required. However, all the instances of the PropertyProxyValidator class you place in a page integrate with the ASP.NET validation system, and so you can cause validation by calling the Validate method of the Page class, and check the result using the IsValid property of the Page class – this does not occur automatically.

    By integrating the Validation Application Block with your applications, you can reuse your validation rules across several levels of your system architecture. Integration allows you reuse the validators that are associated with your application classes when you perform validation at the user-interface level for ASP.NET . The integration provided by the Validation Application Block at the user-interface level does the following:

    • It provides a way to associate properties of validated application objects with user-interface controls.
    • It provides a way to convert values from an input data type to an application-specific data type. For example, you can convert a string input to a System.DateTime value.
    • It helps avoid coding errors in type names and property names. For example, it throws exceptions when type names or property names cannot be found.
    • It does not require instances of application objects to be created in order for validators to be invoked at the user-interface level. In other words, you do not need to instantiate a Customer object just to check whether an input string entered by the user meets the validation requirements of the Customer.Name property.

    To use the PropertyProxyValidator class, you simply add instances to the ASP.NET page, either by declaring them within the .aspx file or by generating instances dynamically at runtime and adding them to the Controls collection of the Page object or another container control. The process is identical to adding ASP.NET built-in validation controls such as the RequiredFieldValidator or any other ASP.NET control) to a page.

    The only real differences when working with the Validation Application Block compared to the ASP.NET validation controls are:

    • You must include an @Register directive in the ASP.NET page to register the integration assembly that contains the PropertyProxyValidator control:
      <%@ Register Assembly="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet" Namespace="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet" TagPrefix="EntLibValidators" %>
    • You use only one type of validation control, the PropertyProxyValidator control, for all validation operations. The actual operation and parameters appear in the configuration file or in attributes applied to the target object class and its members. You should have a target object class defined that supports validation through configuration or attributes.
    • You specify the name of the rule set, the type name of the target object, and the target object member (method or property name) in the PropertyProxyValidator control declaration. For example:
    <EntLibValidators:PropertyProxyValidator ID="CustomerNameValidator" runat="server" ControlToValidate="txtName" PropertyName="Name" RulesetName="ExampleRuleSet" SourceTypeName="TestApp.Customer" EnableViewState="false"/>

    For each validated UI input control, specify that input control’s ID property as the ControlToValidate property of the PropertyProxyValidator control. Also set the RulesetName, SourceTypeName, and PropertyName properties to the appropriate values based on your application configuration.

    Our test application displays textboxes for the six properties of the target object. If you click the Submit button, after entering values in the text boxes, the code creates an instance of the target class with valid values, performs validation on the object, and displays the property values and the validation result in the page.

    If you now edit the values in the text boxes so that they are outside the range of valid values, and click the Submit button again, the page displays a list of errors it encounters when validating the new object instance.

    For each invalid property value, the page displays the contents of the MessageTemplate for the validator, the name of the target property, the value of the Tag property of the validator, and the type name of the target object.

    To validate the UI control values, add code to the handler for the button or other control that submits the page. A separate routine named CreateLocalCompanyObject performs the task of applying the validated UI values to a new instance of the target object, and displaying its properties in the page:

    // force validators to check control values Page.Validate(); if (Page.IsValid) { // create sample object instance and set properties CreateLocalCustomerObject(); } else { lblResult.Text = "Validation errors encountered by ASP.NET Integration Validators<p />"; }
    private void CreateLocalCustomerObject() { // create sample object instance and set properties TestApp.Customer objCustomer = new TestApp.Customer(); objCustomer.Name = txtName.Text; objCustomer.Address = txtAddress.Text; objCustomer.City = txtCity.Text; objCustomer.PostalCode = txtPostalCode.Text; objCustomer.EmployeeCount = Int32.Parse(txtEmployees.Text); objCustomer.LastReportDate = DateTime.Parse(txtReportDate.Text); // display and validate property values DisplayAndValidateSampleObject(objCustomer); }

    Unlike the ASP.NET UI validation controls, which react to an event in the ASP.NET page cycle to perform validation, the Validation Application Block validators must be explicitly executed by calling the static Validate method of the block. The easiest way to do this is to use the Validation façade. The façade allows you to you to create a Validator instance and validate an object with a single line of code. This is shown in the following code example.

    Customer cust = new Customer(); ValidationResults results = Validation.Validate<Customer>(cust, "rulesetname");

    If you do not want to use the façade, you can use the following code, which is the equivalent.

    Customer cust = new Customer(); Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>("rulesetname"); ValidationResults results = validator.Validate(cust);

    Use the CreateValidator method on the ValidationFactory class to first get a reference to the Validator instance, and then use the Validate method to validate the object.

    The Validate method of the Validation façade accepts as parameters the name of the object to validate, and optionally the names of the validation rule sets to apply. For example, if you have only a single rule set named RuleSetA defined in the configuration of the application, you can apply this rule set to an object named customer using the following code.

    ValidationResults results = Validation.Validate(cust, "RuleSetA");

    If you have two rule sets named RuleSetA and RuleSetB defined in the configuration of the application, you can apply the rules from both using the following code.

    ValidationResults results = Validation.Validate(cust, "RuleSetA", "RuleSetB");

    The Validate method returns an instance of the ValidationResults class, which is a collection containing a ValidationResult instance for each validation failure. The ValidationResult class exposes properties that allow you to obtain the value of the Key (the member name if available), the Message describing the validation error, the value of the validator Tag property, the type name of the Target object, and the name of the Validator. There is also the NestedValidationResults property, which exposes a ValidationResults collection containing the validation errors for any nested validators, when using a composite validator.

    Our DisplayAndValidateSampleObject() function calls the Validate method, and then checks if there were any validation errors by examining the IsValid property of the returned ValidationResults collection. If there are errors, the code iterates through the collection adding the values of the Key, Tag, and Target properties of each ValidationResults instance to the StringBuilder. If there are no errors, it adds a suitable message to the StringBuilder instead. Finally, the code displays the contents of the StringBuilder in a Label control on the page:

    ... // validate the property values using the configured rule set ValidationResults results; results = Validation.Validate(targetObject, "ExampleRuleSet"); // get validation results if (!results.IsValid) { builder.Append("<b>Validation Errors:</b>:<br />"); foreach (ValidationResult result in results) { builder.Append(String.Format("- <b>{0}</b><br />", result.Message)); builder.Append(String.Format("&nbsp; (Key: {0}, ", result.Key.ToString())); builder.Append(String.Format("Tag: {0}, ", result.Tag)); builder.Append(String.Format("Target: {0})<br />", result.Target.ToString())); } } else { builder.Append("All object property values are valid."); } // display results in Label control lblResult.Text = builder.ToString(); ...

    It is always a good idea to repeat on the server any UI validation you carry out before using posted values in your application. This protects against spoofing attacks; and against issues that may arise is client browsers do not fully support or correctly process client-side script. However, unlike the ASP.NET validation controls, the PropertyProxyValidator controls only perform validation server-side, and not through client-side script.

    Using the Enterprise Library Validation Application Block in ASP.NET applications allows concentrating on the use of rule sets that allow validation across the UI and object instances within the application tiers.

    While ASP.NET provides a fully-featured set of UI validation controls, these do not always fulfill the requirements of enterprise-level applications. The Validation Application Block supports a wider range of validators, has features to allow composition and negation of validators, and supports validation using configuration rules as well as attributes applied directly to classes and class members.

    One should combine the Validation Application Block validators with the ASP.NET built-in validators as required. The PropertyProxyValidator control that supports ASP.NET integration is itself a descendant of the ASP.NET validator base class, and so behaves and can be handled in the same way as the ASP.NET validation controls.

     

    Enterprise Library 4.0 – Just Released

    May 18, 2008 1 comment

    Congratulations to the Enterprise Library Team for their release of Enterprise Library 4.0. A few enhancements and bug fixes in this release, but most importantly it comes with Unity IoC Integration. As you may or may not know, Unity is Microsoft Patterns & Practices lightweight, extensible dependency injection container with support for constructor, property, and method call injection. The patterns & practices Enterprise Library is a collection of reusable application blocks designed to assist software developers with common enterprise development challenges. This following application blocks are included: Caching Application Block, Cryptography Application Block, Data Access Application Block, Exception Handling Application Block, Logging Application Block, Policy Injection Application Block, Security Application Block, Validation Application Block, and Unity Application Block.

    Download Enterprise Library 4.0 here.

    This release of Enterprise Library includes the following:

    • Integration with the Unity Application Block
    • Windows Management Instrumentation (WMI) 2.0 support and improved instrumentation
    • Performance improvements (particularly, in the Logging Application Block)
    • Pluggable Cache Managers
    • Visual Studio 2008 support
    • Bug fixes

    Note: existing public APIs (v3.1) are still supported.

    Check out CodePlex for Unity and PnPGuidance as well.

    The Application Block Software Factory and the Strong Naming Guidance Package are not included in this release but are available as a separate download. Thus, there is no longer a dependency on Guidance Automation Extensions (GAX).

    If you already know and love the Enterprise Library:

    • Check out the change log for this release;
    • Upgrade to V4.0—no code change is required—simply update the references to the corresponding application block assemblies and to the common assemblies;
    • Download the updated QuickStarts and run through the Unity-integrated examples to get the flavor of new dependency injection style of using the Enterprise Library