Chapter 2. Designing the Layered Architecture

Since I have decided that the application architecture will use a layered approach, it is time to create the Visual Studio solution to host these layers.

The Problem

In order to implement the layered approach correctly, there are some steps that I will need to follow:

  1. The Visual Studio solution must be organized make it very obvious where the layers have been implemented in the code modules.

  2. Each individual layer needs to be designed as well, and needs to include the design patterns and technologies for each layer.

  3. I need to decide what functionality belongs in each of the layers.

  4. An application framework needs to be built that will simplify coding the application.

The Design

In this chapter, there are two main items that need to be designed, and those items are the Visual Studio solution and the actual architectural layers of the SmartCA application.

Designing the Visual Studio Solution

As stated earlier, the first step in implementing the layered architecture is to create a Visual Studio solution that will support the approach.

The initial skeleton for the solution will hold four projects, one for each layer of the application. Figure 2.1 below shows this initial design.

Initial code skeleton design.

Figure 2.1. Initial code skeleton design.

The first three projects in the solution are basic C# Class Library projects, and the last project, SmartCA.Presentation, is actually a WPF project.

As can be seen from the names of the projects in the solution, the namespace pattern that will be used is always SmartCA.<Layer Name>. There will be cases where an extra project may be required even though it still belongs in one of the four layers. Usually, this happens in the infrastructure layer, where you may be implementing some functionality that needs to be separated from the rest of the Infrastructure project. In that particular case, the naming standard that I will follow is SmartCA.<Layer Name>.<Some other functionality name >. An example is a project with a name and namespace combination of SmartCA.Infrastructure.Caching. These types of projects can be added later if and when they are needed.

Designing the Architectural Layers

Now that the namespace naming pattern has been established for the layers, it is time to start the layers. Just to refresh your memory from Chapter 1, the layers I will be building are the application, domain, infrastructure, and presentation (a.k.a. UI) layers.

Designing the Application Layer

I would like to approach the application layer as an application programming interface (API), or almost a façade, to the domain model. The reason I say almost a façade is because the application will be doing a little bit more than just making it simple to use the domain model; it will also be coordinating actions between different domain objects as well as maintaining the state of a particular task. The classes in this layer will be composed of mostly static methods, thus making it easy for a class in the presentation layer to do some work. An example is having a ProjectService class in the application layer that has very simple methods to load and save a Project, such as Project.GetProject(1) and Project.Save(project). This could also be the layer that web service methods would call to get or save their data. Another example is using the application layer to coordinate actions between domain objects and infrastructure objects, such as saving a project and then sending an email to all of the interested parties in management.

Designing the Domain Layer

The domain layer will be designed using the POCO approach (POCO stands for Plain-Old CLR Objects). It is my intent to make the domain model as free from any distractions as possible, including having to implement several persistence-related interfaces or inherit from classes that have nothing to do with the business model. The idea is for the classes in the domain layer to be as persistent-ignorant as possible.

Important Domain-Driven Design Concepts

Before getting too deep into the design of the SmartCA application, there are some common Domain-Driven Design terms and concepts that must be discussed. Although I am not going to go into great detail about them here, they still need to be talked about before moving forward. In order to get a deeper understanding of these concepts I highly recommend reading Domain-Driven Design: Tackling Complexity in the Heart of Software (Addison-Wesley, 2004) by Eric Evans; Applying Domain-Driven Design and Patterns, With Examples in C# and .NET (Addison-Wesley, 2006) by Jimmy Nilsson; and Patterns of Enterprise Application Architecture (Addison-Wesley, 2003) by Martin Fowler. The main point of this book is to adhere to these concepts as much as possible while building the SmartCA application.

Entities

One of the most important fundamental concepts to understand is the definition of Entity in Domain-Driven Design. According to Evans "An object primarily defined by its identity is called an Entity." Entities are very important in the domain model, and need to be designed carefully. Sometimes what people think of as an entity in one system is not an entity in another system; for example, an address. In some systems, an address may not have an identity at all; it may only represent attributes of a person or company. In other systems, such as a cable television company or a utility company, the address could be very important. In those systems, the address is important as an identity because the billing may be tied directly to the address. In that case, the address would definitely be classified as an entity. In other systems, such as an e-commerce web site, the address may only be used for determining where to send an order, and the identity of the address may not really matter much, just the attributes of the address so that the order can be fulfilled. In those types of cases, the address becomes what is called in Domain-Driven Design a Value object.

Value Objects

Unlike Entity objects, Value objects have no identity. There is no need to track the object's identity, and it is very easy to create and discard. Most of the time, Value objects usually contain either just data or just behavior. The ones that contain only data are also known as Data Transfer Objects (DTOs) (Fowler, Patterns of Enterprise Application Architecture, 401). A very common scenario is for an Entity to contain other Value objects. There are also times where Value objects can contain other Value objects, even other Entity objects. Most of the time, as in the case of the address example used earlier, they are a group of attributes that make up a conceptual whole but without an identity.

It is recommended that Value objects be immutable, that is, they are created with a constructor, with all properties being read-only. To get a different value for the object, a new one must be created. A perfect example of this is the System.String class. Value objects do not always have to be immutable, but the main rule to follow is that if the object is going to be shared, then it needs to be immutable.

In distinguishing between Entity objects and Value objects, if the object does not have an identity that I care about, then I classify it as a Value object.

Services

Sometimes, when designing a domain model, you will have certain types of behavior that do not fit into any one class. Trying to tack on the behavior to a class to which it really does not belong will only cloud the domain model, but .NET, and all other object-oriented languages, requires the behavior to live in some type of object, so it cannot be a separate function on its own (as you might find in JavaScript or other scripting languages). The type of class that becomes the home for this behavior is known in Domain-Driven Design as a Service.

A Service class has no internal state and can simply act as an interface implementation that provides operations. This concept is very similar to web services. Services typically coordinate the work of one or more domain objects, and present the coordination as a well-known operation. It is also important to note that some services may live in the application layer, some may live in the domain layer, and others may live in the infrastructure layer.

Application Layer Services

The services that live in the application layer typically coordinate the work of other services in other layers. Consider an order fulfillment service. This service probably takes in an order message in the format of XML data, calls a factory to transform the XML into an object, and then sends the object to the domain layer for processing. After processing has been completed, the service may need to send out a notification to a user, and it may delegate that to an infrastructure layer service.

Domain Layer Services

In keeping with the order fulfillment example, the domain layer service would be responsible for interacting with the right Entity objects, Value objects, and other domain layer objects necessary to process the order in the domain. Ultimately, the service would return some type of result from the operation so that the calling service could take the necessary actions.

Infrastructure Layer Services

In the same order fulfillment scenario, the infrastructure layer service may need to do things like sending the user an order confirmation email letting them know that their order is being processed. These types of activities belong in the infrastructure layer.

Aggregates

In Domain-Driven Design speak, an Aggregate is a term used to define object ownership and the boundaries between objects and their relationships. It is used to define a group of associated objects that are to be treated as one unit in regard to data changes. For example, an Order class and its associated line items can be considered to be part of the same Order Aggregate, with the Order class being the root of the Aggregate. That brings me to a very important rule, and that is each Aggregate can only have one root object, and that object is an Entity object. The root of an Aggregate can hold references to the roots of other Aggregates, and objects inside of an Aggregate can hold references to one another, but nothing outside of the Aggregate boundary can access the objects inside of the Aggregate without going through that Aggregate's root object.

It is easier to understand this concept with an example. The example I always use is the canonical Order Aggregate. An Order object is the root of its own Aggregate, and it contains objects such as Line Items (which can contain Products) and Customers. To get to a Line Item object, I would have to go through the Order Aggregate root object, the Order object. If I only wanted get some data about a Customer, and not the Order, I might choose to start from the Customer Aggregate. I could move from the Order Aggregate to the Customer Aggregate, since the Order Aggregate contains an instance of a Customer object. On the other hand, I could get to a Customer's Order by going through the Customer Aggregate first, and then traversing the relationship between a Customer and his Orders. In this case, the relationship is bidirectional, and I could choose to start from the Customer Aggregate or from the Order Aggregate, depending on the use case. The key to remember is that both the Customer and the Order are the roots of their own Aggregate, and can also hold references to other Aggregate roots. I could not go directly from a Customer to a Line Item; I would first need to go to the Customer's Order, and then travel from there to the Line Item.

Defining the Aggregates in a domain model is one of the hardest activities to get right in Domain-Driven Design, and this is where you really need the help of an expert in the business domain that you are dealing with to determine the right boundaries and associations. It is also an area that I end up refactoring a lot as I begin to understand more about the business model of an application.

Repositories

According to Eric Evans, a repository "represents all objects of a certain type as a conceptual set (usually emulated)" (Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software, 151). He also goes on to say that for every object that is an Aggregate, create a repository for the object and give it the look and feel of an in-memory collection of objects of that particular type. The access to the repository must be through a well-known interface. The main point of repositories is to keep the developer focused on the domain model logic, and hide the plumbing of data access behind well-known repository interfaces. This concept is also known as persistence ignorance, meaning that the domain model is ignorant of how its data is saved or retrieved from its underlying data store or stores.

Factories

As the Entities and their associated Aggregates start to grow in the domain layer, it becomes increasingly more difficult to build up objects consistently just using constructors. Lots of times there is intimate knowledge needed to construct an Aggregate and all of its relationships, constraints, rules, and the like. Instead of making the Entity objects themselves responsible for this creation, it is better to have a Factory that knows how to build these types of objects, and thus avoid clouding up the code of an Entity object.

In Domain-Driven Design, there are two types of Factories, those for building the root Entity of an Aggregate (usually from some type of resultset data) and those for building Value objects (usually from some type of configuration data).

Using Repositories in the Domain Layer

If I can get away with it, I will try not to let any of my domain model classes know about any of the repositories. This goes a long way towards persistence ignorance, but it is not always an easy thing to accomplish. I would like to restrict repositories so that only their interfaces will live in the domain layer. If I am successful, a domain model class can talk to a repository interface if it really needs to, yet the implementation of the actual repositories will be in the infrastructure layer. This is better known as the Separated Interface pattern (Fowler, Patterns of Enterprise Application Architecture, 476–479), where the interface is defined in a separate assembly from its implementation. My goal can also be aided by having a factory provide the implementation of the interface requested, and therefore the domain model classes may need to have an extra dependency on the Repository Factory if they need to create and use the repository implementation classes.

Using the Layered Supertype Pattern

Since Evans defines an Entity as "an object that is distinguished by identity, rather than its attributes" (Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software, 92), we know that all of our entity classes are going to need some type of data type to distinguish their identities. This would be a good opportunity to use Fowler's Layered Supertype pattern, which is defined as "a type that acts as the supertype for all types in its layer" (Fowler, Patterns of Enterprise Application Architecture, 475). Having all entities inherit from an entity base class type will help eliminate some duplicate properties and behavior in the domain entity classes. The use of this base class is purely for convenience, and I feel that it will not distract our model at all; in fact, it will be easier to distinguish between which classes are entities and which ones are value objects.

Designing the Infrastructure Layer

The infrastructure layer is where all of the SmartCA application's plumbing lives. Any type of framework, data access code, calls to web service calls, and so forth will live in this layer. A perfect example of this is the SmartCA application's Repository Framework implementation, which I will dive into in the Solution section of this chapter, that lives inside of the infrastructure layer. Not only can the infrastructure layer hold infrastructure for the domain layer, but it can also hold infrastructure code and logic for any of the other layers, including those that meet its own needs.

Designing the Presentation Layer

The goal in designing the presentation layer is to keep it as thin as possible, very similarly to the application layer. One of the main pitfalls to avoid is embedding any business logic in the presentation layer. The presentation layer has two main responsibilities:

  1. Interpret the user's commands and send the user's requests down to the application layer or domain layer.

  2. Show information to the user.

In order to help the presentation layer carry out its responsibilities, I will be using a new pattern developed by John Gossman of the Microsoft WPF team, called the Model-View-ViewModel pattern. The implementation of this pattern will be discussed in the Solution section.

The Solution

Now that I have detailed how the Visual Studio solution and all of the architectural layers should be designed, it is time to start implementing these designs. That means I finally get to do my favorite thing, which is writing code!

Implementing the Visual Studio Solution

In keeping with the layered architecture diagram in Figure 1.2, the dependencies of the layers can only go down from higher levels to lower levels, that is, the presentation layer can depend on the application layer, but the application layer cannot have a dependency on the presentation layer. Figure 2.2 illustrates the dependencies by showing the references between the projects.

Initial code skeleton design with dependencies.

Figure 2.2. Initial code skeleton design with dependencies.

The project that is really the root of dependencies is the SmartCA.Infrastructure project, as it is referred to by all of the other assemblies and it does not refer to any of the other assemblies.

Implementing the Architectural Layers

This section may sound a little bit misleading, because if I were to implement all of the architectural layers here, then the application would be finished and the book would be over! What I am going to show you in this section is a lot of Infrastructure code that the other layers of the application will be using. I will first start with the Layered Supertype implementation, followed by the Repository Framework, and lastly I will conclude with the Model-View-ViewModel pattern implementation that will be used in the presentation layer.

Layered Supertype

The layered supertype I will use is an abstract class named EntityBase, with the intention that all Entity classes in the domain model will need to inherit from this class to gain their identity. This class will live in the SmartCA.Infrastructure project, as it is not really part of the domain logic, but it is providing necessary functionality to the domain model. Here is the code for this class:

using System;

namespace SmartCA.Infrastructure.DomainBase
{
    public abstract class EntityBase
    {
        private object key;

        /// <summary>
        /// Default Constructor.
        /// </summary>
        protected EntityBase()
               : this(null)
        {
        }

        /// <summary>
        /// Overloaded constructor.
        /// </summary>
        /// <param name="key">An <see cref="System.Object"/> that
        /// represents the primary identifier value for the
        /// class.</param>
        protected EntityBase(object key)
        {
            this.key = key;
        }

        /// <summary>
        /// An <see cref="System.Object"/> that represents the
        /// primary identifier value for the class.
        /// </summary>
        public object Key
        {
            get
            {
                return this.key;
            }
        }

The first part of the class contains a default constructor and an overloaded constructor that allow a key value to be passed in. The key that was passed in is also exposed as a read-only property. Currently, I am leaving the Key property's type as a System.Object, because I am not really sure yet if the keys to the entities will be Guids, Integers, an so on. Also, some key data types on entity objects may be different from others, and so for right now this gives me the most flexibility.

The next part of the code implements all of the necessary equality tests to determine whether two entity objects are equal to each other. These come in very handy later when comparing entity values in collections, trying to find matches, and so forth.

#region Equality Tests

        /// <summary>
        /// Determines whether the specified entity is equal to the
        /// current instance.
        /// </summary>
        /// <param name="entity">An <see cref="System.Object"/> that
        /// will be compared to the current instance.</param>
        /// <returns>True if the passed in entity is equal to the
        /// current instance.</returns>
        public override bool Equals(object entity)
        {
            if (entity == null || !(entity is EntityBase))
            {
                return false;
            }
            return (this == (EntityBase)entity);
        }

        /// <summary>
        /// Operator overload for determining equality.
        /// </summary>
        /// <param name="base1">The first instance of an
        /// <see cref="EntityBase"/>.</param>
        /// <param name="base2">The second instance of an
        /// <see cref="EntityBase"/>.</param>
        /// <returns>True if equal.</returns>
        public static bool operator ==(EntityBase base1,
            EntityBase base2)
        {
            // check for both null (cast to object or recursive loop)
            if ((object)base1 == null && (object)base2 == null)
            {
                return true;
            }

            // check for either of them == to null
            if ((object)base1 == null || (object)base2 == null)
            {
                return false;
            }

            if (base1.Key != base2.Key)
{
                return false;
            }

            return true;
        }

        /// <summary>
        /// Operator overload for determining inequality.
        /// </summary>
        /// <param name="base1">The first instance of an
        /// <see cref="EntityBase"/>.</param>
        /// <param name="base2">The second instance of an
        /// <see cref="EntityBase"/>.</param>
        /// <returns>True if not equal.</returns>
        public static bool operator !=(EntityBase base1,
            EntityBase base2)
        {
            return (!(base1 == base2));
        }

        /// <summary>
        /// Serves as a hash function for this type.
        /// </summary>
        /// <returns>A hash code for the current Key
        /// property.</returns>
        public override int GetHashCode()
        {
            if (this.key != null)
            {
                return this.key.GetHashCode();
            }
            else
            }
                return 0;

            }
        }

This behavior is necessary for comparing, sorting, and matching entity objects. This is nice because this plumbing type of code is encapsulated in the infrastructure layer and keeps the domain layer's entity objects free from these distractions.

Repository Framework

For the SmartCA application, I have decided to implement a hybrid Repository Framework. By hybrid, I mean a cross between a pure Repository Framework, where all repositories have the same interface, and a custom repository implementation for each aggregate root.

The Interfaces

The hybrid framework will contain a generic IRepository<T> interface, which will live in the SmartCA.Infrastructure.RepositoryFramework namespace in the SmartCA.Infrastructure assembly, which has the following signature:

using System;
using SmartCA.Infrastructure.DomainBase;

namespace SmartCA.Infrastructure.RepositoryFramework
{
    public interface IRepository<T> where T: EntityBase
    {
        T FindBy(object key);
        void Add(T item);
        T this[object key] { get; set; }
        void Remove(T item);
    }
}

Using .NET Generics helps a great deal here, as it allows for the IRepository<T> interface to be reused in many places of the application, and because of the where clause on T, it restricts the data type to being a class that derives from EntityBase, the domain model's layered supertype. An interesting note about this interface is that there is actually an indexer (T this[object key] { get; set; }). I added this to emphasize the concept that a repository should emulate a collection of objects in memory.

You may have noticed that I did not put a Find or FindBy method on this interface that takes some type of generic predicate or expression. I did this intentionally. Based on my previous experience, this can get pretty complicated, and so I have decided to put all of the Find type of methods in Aggregate-specific types of repositories, an example of which would look like the IProjectRepository interface shown below:

using System;
using System.Collections.Generic;
using SmartCA.Infrastructure.RepositoryFramework;

namespace SmartCA.Model.Projects
{
    public interface IProjectRepository: IRepository<Project>
    {
        IList<Project> FindBy(object sector, object segment,
            bool completed);
    }
}

This way, if you want to program against the general interface (IRepository<T>) you can, but you can also program against a more specific interface if you need to add more specialized methods to your repository, such as more granular Find methods. It essentially gives you the option to refactor things later without too much pain.

The Repository Factory

Earlier in the Design section of this Chapter I talked about the importance of the domain model classes being able to use a particular Repository interface without needing a reference to the associated repository implementation in the infrastructure layer. This concept was defined as the Separated Interface pattern, and I mentioned that I would need a Factory to provide the implementation of the Repository interface that was requested. That Factory is called the Repository Factory and is exactly what I going to implement in this section.

Configuration Section

In order to eliminate any hard-coding of repository class names in the Repository Factory, I have chosen to use configuration along with the Factory to make it very easy to change what repositories get created at runtime by changing a few configuration settings. Not only does this make use of the previously mentioned Separated Interface pattern, but it also very closely resembles the ASP.NET Provider pattern, in that the provider's Factory creates its objects based upon configuration settings.

Here is what the configuration section for the Repository Factory looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="repositoryMappingsConfiguration"

type="SmartCA.Infrastructure.RepositoryFramework.Configuration.RepositorySettings,
SmartCA.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </configSections>
  <repositoryMappingsConfiguration>
    <repositoryMappings>
      <repositoryMapping interfaceShortTypeName="IProjectRepository"

repositoryFullTypeName="SmartCA.Infrastructure.Repositories.ProjectRepository,
SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" />
    </repositoryMappings>
  </repositoryMappingsConfiguration>
</configuration>

The configuration section is really just storing the mappings of interface types to their implementations, as can be seen in the repositoryMapping element in the configuration file. What this means is that a repository implementation could be changed in the application's configuration file without having to recompile the application.

Configuration Section Handling

In order to support this functionality, I have added a Configuration folder under the RepositoryFramework folder of the SmartCA.Infrastructure project (see Figure 2.3).

RepositoryFramework Configuration folder.

Figure 2.3. RepositoryFramework Configuration folder.

The job of the classes in the Configuration folder is to read and copy the settings from the repositoryMappingsConfiguration configuration section into a nice object model that the RepositoryFactory can consume in order to do its job. The root class for this configuration-section-handling functionality is the RepositorySettings class, which inherits from the .NET Framework ConfigurationSection class.

using System;
using System.Configuration;

namespace SmartCA.Infrastructure.RepositoryFramework.Configuration
{
    public class RepositorySettings: ConfigurationSection
    {

[ConfigurationProperty(RepositoryMappingConstants.ConfigurationPropertyName,
            IsDefaultCollection = true)]
        public RepositoryMappingCollection RepositoryMappings
        {
            get { return
(RepositoryMappingCollection)base[RepositoryMappingConstants.ConfigurationProperty
Name]; }
        }
    }
}

The class is very simple, since the .NET Framework's ConfigurationSection class does most of the work. Its main purpose is to return the collection of repositories defined in configuration into a RepositoryMappingCollection data type. I have defined the name of the configuration element that represents the collection of repositories in a separate class named RepositoryMappingConstants.

using System;

namespace SmartCA.Infrastructure.RepositoryFramework.Configuration
{
    internal static class RepositoryMappingConstants
    {
        public const string ConfigurationPropertyName = "repositoryMappings";
        public const string ConfigurationElementName = "repositoryMapping";
        public const string InterfaceShortTypeNameAttributeName =
"interfaceShortTypeName";
        public const string RepositoryFullTypeNameAttributeName =
"repositoryFullT
ypeName";
        public const string RepositoryMappingsConfigurationSectionName =
"repository
MappingsConfiguration";
    }
}

Since I have to refer to these string values more than once in the Repository Framework configuration code, it's a lot easier to define them with a static constants class. Note that the RepositoryMappingConstants class is marked internal, as the only code needing to know about these constants is in the SmartCA.Infrastructure assembly.

The RepositoryMappingCollection is a little bit more complicated than the RepositorySettings class. Its job is to wrap the repositoryMappings element from the configuration section, and expose it as a strongly typed collection.

using System;
using System.Configuration;

namespace SmartCA.Infrastructure.RepositoryFramework.Configuration
{
    public sealed class RepositoryMappingCollection:
ConfigurationElementCollection
    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new RepositoryMappingElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((RepositoryMappingElement)element).InterfaceShortTypeName;
        }

        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        protected override string ElementName
        {
            get { return RepositoryMappingConstants.ConfigurationElementName; }
        }

        public RepositoryMappingElement this[int index]
        {
            get { return (RepositoryMappingElement)this.BaseGet(index); }
            set
            {
                if (this.BaseGet(index) != null)
                {
                    this.BaseRemoveAt(index);
                }
                this.BaseAdd(index, value);
            }
        }

        public new RepositoryMappingElement this[string interfaceShortTypeName]
        {
            get { return
(RepositoryMappingElement)this.BaseGet(interfaceShortTypeName); }
        }

        public bool ContainsKey(string keyName)
{
            bool result = false;
            object[] keys = this.BaseGetAllKeys();
            foreach (object key in keys)
            {
                if ((string)key == keyName)
                {
                    result = true;
                    break;

                }
            }
            return result;
        }
    }
}

Like the RepositorySettings class, it too inherits from one of the Sytem.Configuration classes, this time the ConfigurationElementCollection class. There is really nothing very special about this class; it is basically just overriding various methods and properties on its base class. One thing that might look a little bit odd is the indexer property for the class.

public new RepositoryMappingElement this[string interfaceShortTypeName]
        {
            get { return
(RepositoryMappingElement)this.BaseGet(interfaceShortTypeName); }
        }

It is actually hiding the base class indexer (by using the new keyword) in order to make it strongly typed instead of exposing the collection item as a System.Object.

The child members that the RepositoryMappingCollection contains are RepositoryMappingElement instances. The RepositoryMappingElement class is what actually holds the mapping between an interface type name and a concrete repository type name.

using System;
using System.Configuration;

namespace SmartCA.Infrastructure.RepositoryFramework.Configuration
{
    public sealed class RepositoryMappingElement: ConfigurationElement
    {
[ConfigurationProperty(RepositoryMappingConstants.InterfaceShortTypeName
AttributeName,
            IsKey = true, IsRequired = true)]
        public string InterfaceShortTypeName
        {
            get
            {
                return (string)this[RepositoryMappingConstants.Interface
ShortTypeNameAttributeName];
            }
            set
{

this[RepositoryMappingConstants.InterfaceShortTypeNameAttributeName] = value;
            }
        }

[ConfigurationProperty(RepositoryMappingConstants.RepositoryFullTypeName
AttributeName,
            IsRequired = true)]
        public string RepositoryFullTypeName
        {
            get
            {
                return
(string)this[RepositoryMappingConstants.RepositoryFullTypeNameAttributeName];
            }
            set
            {

this[RepositoryMappingConstants.RepositoryFullTypeNameAttributeName] = value;
            }
        }
    }
}

Like the other repository mapping configuration classes, this class also inherits from one of the System.Configuration classes, the ConfigurationElement class. With the help of some System.Configuration attributes decorating it, the RepositoryMappingElement class exposes two properties, InterfaceShortTypeName and RepositoryFullTypeName.

The RepositoryFactory Class

Now that the configuration is finished, the RepositoryFactory can use it to create repositories. The RepositoryFactory uses Generic type parameters combined with the mappings from the configuration in order to determine what kind of repository to create. The RepositoryFactory is a static class with one static method, GetRepository.

using System;
using System.Collections.Generic;
using SmartCA.Infrastructure;
using SmartCA.Infrastructure.DomainBase;
using SmartCA.Infrastructure.RepositoryFramework.Configuration;
using System.Configuration;

namespace SmartCA.Infrastructure.RepositoryFramework
{
    public static class RepositoryFactory
    {
        // Dictionary to enforce the singleton pattern
        private static Dictionary<string, object> repositories = new
Dictionary<string, object>();
/// <summary>
        /// Gets or creates an instance of the requested interface. Once a
        /// repository is created and initialized, it is cached, and all
        /// future requests for the repository will come from the cache.
        /// </summary>
        /// <typeparam name="TRepository">The interface of the repository
        /// to create.</typeparam>
        /// <typeparam name="TEntity">The type of the EntityBase that the
        /// repository is for.</typeparam>
        /// <returns>An instance of the interface requested.</returns>
        public static TRepository GetRepository<TRepository, TEntity>()
            where TRepository: class, IRepository<TEntity>
            where TEntity: EntityBase
        {
            // Initialize the provider's default value
            TRepository repository = default(TRepository);

            string interfaceShortName = typeof(TRepository).Name;

            // See if the provider was already created and is in the cache
            if (!RepositoryFactory.repositories.ContainsKey(interfaceShortName))
            {
                // Not there, so create it

                // Get the repositoryMappingsConfiguration config section
                RepositorySettings settings =
(RepositorySettings)ConfigurationManager.GetSection(RepositoryMappingConstants
.RepositoryMappingsConfigurationSectionName);

                // Create the repository, and cast it to the interface specified
                repository =
Activator.CreateInstance(Type.GetType(settings.RepositoryMappings[interfaceShortName]
.RepositoryFullTypeName)) as TRepository;

                // Add the new provider instance to the cache
                RepositoryFactory.repositories.Add(interfaceShortName, repository);
            }
            else
            {
                // The provider was in the cache, so retrieve it
                repository =
(TRepository)RepositoryFactory.repositories[interfaceShortName];
            }
            return repository;
        }
    }
}

The signature of this method is interesting because it uses two Generic type parameters, TRepository and TEntity, with the restrictions that TRepository is a class and implements the IRepository<TEntity> interface, and that TEntity derives from the EntityBase class. Because the Repository Framework is supporting interfaces other than just IRepository<T>, the method cannot just return a type of IRepository<T> for the Repository instance. It must also support returning any interface that implements IRepository<T>, since the repository interface being used can also have additional methods defined in it; that is why TRepository has been declared as a Generic type, so that the factory can support the Repository Framework requirements of being able to pass in a valid Repository interface type and get an instance of the interface (as long as it has been properly defined in the application's configuration file).

The code for the method first uses reflection to get the short type name of the interface type passed in via the Generic TRepository parameter. It then does a lookup in its static dictionary of repositories that have already been created to see if it can pull it out of memory. If it cannot, it then begins the process of using the custom repository configuration objects to find the right repository type to create based on the values in the mappings configuration. When the type is found, the method then uses the reflection capabilities of the Activator object to create an instance of the correct repository based on the mapped type from configuration. Then, after the repository has been created, it is put into the static dictionary of repositories so that it will be available the next time it is requested. Once the repository has been retrieved from memory or created, the instance is returned to the caller.

I decided to use a static dictionary to hold the repositories in order to make them behave like singletons. This is very important for performance reasons, since it can be expensive to build a Repository Factory using reflection every time you need one, especially in Domain-Driven Design architectures, where repositories are used quite frequently. Also, because the repositories are guaranteed to have only one instance per type, I can now do other interesting things, such as enable domain model objects to be cached, refresh the cache when I choose to, and so on. This functionality can have a very positive impact on the performance of the application.

Unit of Work

Since I will be using several repositories to pull data in and out of the database (and possibly other resources), I need a way to keep track of what has been changed. I also need a way to define what sequences of events define a transaction and to be able to commit those sequences of events as a single transaction. One way of doing this is simply to avoid the problem altogether and every time an object changes, just write the change to the data store; however, this pattern usually does not work very well, especially when you need to group actions together into a single transaction.

The answer to this requirement that I am going to use is the Unit of Work pattern, as defined by Martin Fowler (Fowler, Patterns of Enterprise Application Architecture, 184). According to Martin, the Unit of Work "maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems." The Unit of Work needs to know what objects it should keep track of, and Martin goes on to describe two basic ways this can be accomplished:

  • Caller registration—The user of the object has to remember to register with the Unit of Work.

  • Object registration— The objects register themselves with the Unit of Work.

Jimmy Nilsson describes a different approach to the Unit of Work, and that is to let the repositories delegate all of their work to a Unit of Work, and then the Unit of Work then makes all necessary database calls (or other types of resource calls) on behalf of the repositories (Nilsson, Applying Domain-Driven Design and Patterns, With Examples in C# and .NET, 2006). One major benefit of this approach is that the messages sent to the Unit of Work are invisible to the consumer of the repositories, since the repositories are reporting what has been asked of them to the Unit of Work. This also helps promote persistence ignorance in the domain objects, which is what I am striving for.

In his solution, Jimmy implemented object persistence outside of the repository in his Unit of Work implementation. The reasoning for not letting the repositories completely hide the Unit of Work was that he wanted to synchronize changes across several Aggregates (and their respective repositories) in a single logical unit. In order for this to work, the repositories need to have a Unit of Work injected into them at creation time.

I really like Jimmy's idea of hiding the Unit of Work calls in the repositories because it eliminates lots of plumbing calls inside of domain objects or from application-level code. This way, the plumbing stays inside the repository, which itself represents plumbing, and shields the domain object from having to deal with the noise. With that being said, I also would like to have my cake and eat it too. What I mean by that is that I would like to keep the spirit of Jimmy's solution but also still have the repositories be responsible for the data persistence. In order to do that, I have created a few interfaces to help out. The first one being the obvious one, the IUnitOfWork interface:

using System;
using SmartCA.Infrastructure.DomainBase;
using SmartCA.Infrastructure.RepositoryFramework;

namespace SmartCA.Infrastructure
{
    public interface IUnitOfWork
    {
        void RegisterAdded(EntityBase entity, IUnitOfWorkRepository repository);
        void RegisterChanged(EntityBase entity, IUnitOfWorkRepository repository);
        void RegisterRemoved(EntityBase entity, IUnitOfWorkRepository repository);
        void Commit();
    }
}

The IUnitOfWork interface identifies for use the entities that have been added, changed, or removed from the repositories. An instance of this interface must be passed to all repositories that are to participate in a Unit of Work. Then, once all work is completed, I simply call Commit on the interface to commit all of my changes to the appropriate data stores. You may be asking yourself, how in the world can the Unit of Work implementation commit the changes if the repositories are supposed to do the work? The answer is to have the repositories implement a second interface to which the Unit of Work refers. That interface is the IUnitOfWorkRepository interface:

using System;
using SmartCA.Infrastructure.DomainBase;

namespace SmartCA.Infrastructure.RepositoryFramework
{
    public interface IUnitOfWorkRepository
    {
        void PersistNewItem(EntityBase item);
        void PersistUpdatedItem(EntityBase item);
        void PersistDeletedItem(EntityBase item);
    }
}

Because the repositories will implement the IUnitOfWorkRepository interface, the Unit of Work implementation will now be able to call back in to the repositories to make changes to the data store (or stores).

I have created a Unit of Work implementation class called UnitofWork (I know, very creative). It essentially keeps a list of the three types of changes, and then cycles through each of them during commit time and talks to the right repository to persist the changes.

using System;
using System.Collections.Generic;
using SmartCA.Infrastructure.DomainBase;
using SmartCA.Infrastructure.RepositoryFramework;
using System.Transactions;

namespace SmartCA.Infrastructure
{
    public class UnitOfWork: IUnitOfWork
    {
        private Dictionary<EntityBase, IUnitOfWorkRepository> addedEntities;
        private Dictionary<EntityBase, IUnitOfWorkRepository> changedEntities;
        private Dictionary<EntityBase, IUnitOfWorkRepository> deletedEntities;

        public UnitOfWork()
        {
            this.addedEntities = new Dictionary<EntityBase,
                                     IUnitOfWorkRepository>();
            this.changedEntities = new Dictionary<EntityBase,
                                       IUnitOfWorkRepository>();
            this.deletedEntities = new Dictionary<EntityBase,
                                       IUnitOfWorkRepository>();
        }

        #region IUnitOfWork Members

        public void RegisterAdded(EntityBase entity,
            IUnitOfWorkRepository repository)
        {
            this.addedEntities.Add(entity, repository);
        }

        public void RegisterChanged(EntityBase entity,
            IUnitOfWorkRepository repository)
        {
            this.changedEntities.Add(entity, repository);
        }

        public void RegisterRemoved(EntityBase entity,
            IUnitOfWorkRepository repository)
        {
            this.deletedEntities.Add(entity, repository);
        }

        public void Commit()
        {
            using (TransactionScope scope = new TransactionScope())
            {
                foreach (EntityBase entity in this.deletedEntities.Keys)
                {
                    this.deletedEntities[entity].PersistDeletedItem(entity);
                }

                foreach (EntityBase entity in this.addedEntities.Keys)
                {
this.addedEntities[entity].PersistDeletedItem(entity);
                }

                foreach (EntityBase entity in this.changedEntities.Keys)
                {
                    this.changedEntities[entity].PersistDeletedItem(entity);
                }

                scope.Complete();
            }

            this.deletedEntities.Clear();
            this.addedEntities.Clear();
            this.changedEntities.Clear();
        }

        #endregion
    }
}

The methods in the IUnitOfWork Members region of the class will get called by the repositories, and the repositories actually pass in their own instances to the UnitOfWork class when they call these methods. When these methods are called, the entity and its associated IUnitOfWorkRepository instance are added to their respective dictionary object, depending whether the call was an add, change, or remove registration.

Then, in the Commit method, the UnitOfWork cycles through all of the deletions, additions, and updates, respectively, and calls back on the associated IUnitOfWorkRepository instance to persist the changes to the correct data store. The entire operation is wrapped up in a transaction using the .NET Framework's TransactionScope class, which knows how to enlist the right type of transaction properly, be it just a local transaction or a distributed transaction. Once everything has been committed, the entity-repository dictionaries are then reset to empty.

The Repository Base Classes

In order to eliminate a lot of duplicate code, I have decided to put in some abstract base classes from which the repositories will inherit common code. This should make it easier to code the concrete repository classes.

The RepositoryBase<T> Class

This is the first repository base class and its main job is to lend a helping hand to its derived repositories in regard to implementing the Unit of Work pattern. It also helps out with the indexer implementation of the IRepository<T> interface.

using System;
using SmartCA.Infrastructure.DomainBase;

namespace SmartCA.Infrastructure.RepositoryFramework
{
    public abstract class RepositoryBase<T>
   : IRepository<T>, IUnitOfWorkRepository where T: EntityBase
{
        private IUnitOfWork unitOfWork;

        protected RepositoryBase()
            : this(null)
        {
        }

        protected RepositoryBase(IUnitOfWork unitOfWork)
        {
            this.unitOfWork = unitOfWork;
        }

        #region IRepository<T> Members

        public abstract T FindBy(object key);

        public void Add(T item)
        {
            if (this.unitOfWork != null)
            {
                this.unitOfWork.RegisterAdded(item, this);
            }
        }

        public void Remove(T item)
        {
            if (this.unitOfWork != null)
            {
                this.unitOfWork.RegisterRemoved(item, this);
            }
        }

        public T this[object key]
        {
            get
            {
                return this.FindBy(key);
            }
            set
            {
                if (this.FindBy(key) == null)
                {
                    this.Add(value);
                }
                else
                {
                    this.unitOfWork.RegisterChanged(value, this);
                }
            }
        }
#endregion

        #region IUnitOfWorkRepository Members

        public void PersistNewItem(EntityBase item)
        {
            this.PersistNewItem((T)item);
        }

        public void PersistUpdatedItem(EntityBase item)
        {
            this.PersistUpdatedItem((T)item);
        }

        public void PersistDeletedItem(EntityBase item)
        {
            this.PersistDeletedItem((T)item);
        }

        #endregion

        protected abstract void PersistNewItem(T item);
        protected abstract void PersistUpdatedItem(T item);
        protected abstract void PersistDeletedItem(T item);
    }
}

This class implements both the IRepository<T> interface and the IUnitOfWorkRepository interface, and it is optionally injected with the IUnitOfWork interface in its constructor. Its main job in implementing the IRepository<T> interface is mainly to call back into the IUnitOfWork interface instance to let it know when something has been added, removed, or changed. The other IRepository<T> method without an implementation in this class, T FindBy(object key), is actually declared as an abstract method to be implemented by one of the derived repository classes.

All of the methods on the IUnitOfWorkRepository interface are implemented in this class, but really as a pass-through to some more abstract methods that the derived repositories have to implement. I did this to avoid having to cast from EntityBase to the types being used inside all of the repository implementations. Instead, the casting is performed in this class and then delegated to the more strongly typed, Generic-enabled abstract methods (protected abstract void PersistNewItem(T item), protected abstract void PersistUpdatedItem(T item), and protected abstract void PersistDeletedItem(T item)). This way, the code for the casting is centralized, and the concrete repositories can deal with the strongly typed entities that they know and represent.

The SqlCeRepositoryBase<T> Class

Since the architecture of this application dictates that we write and read all data to and from a local SQL Server CE database, a lot of duplicate SQL data access type of code can be eliminated in the Repository classes by building a base class to handle these types of operations. I decided to name this class SqlCeRepositoryBase, in order to make its purpose obvious. This class makes it very easy for its derived Repository classes to talk to the local SQL CE database.

using System;
using System.Collections.Generic;
using SmartCA.Infrastructure.RepositoryFramework;
using SmartCA.Infrastructure.DomainBase;
using Microsoft.Practices.EnterpriseLibrary.Data.SqlCe;
using Microsoft.Practices.EnterpriseLibrary.Data;
using System.Data;
using System.Data.Common;
using SmartCA.Infrastructure.EntityFactoryFramework;

namespace SmartCA.Infrastructure.Repositories
{
    public abstract class SqlCeRepositoryBase<T>: RepositoryBase<T>
        where T: EntityBase
    {
        #region AppendChildData Delegate

        /// <summary>
        /// The delegate signature required for callback methods
        /// </summary>
        /// <param name="entityAggregate"></param>
        /// <param name="childEntityKey"></param>
        public delegate void AppendChildData(T entityAggregate,
            object childEntityKeyValue);

        #endregion

        #region Private Members

        private Database database;
        private IEntityFactory<T> entityFactory;
        private Dictionary<string, AppendChildData> childCallbacks;

        #endregion

        #region Constructors

        protected SqlCeRepositoryBase()
            : this(null)
        {
        }

        protected SqlCeRepositoryBase(IUnitOfWork unitOfWork)
            : base(unitOfWork)
        {
            this.database = DatabaseFactory.CreateDatabase();
            this.entityFactory = EntityFactoryBuilder.BuildFactory<T>();
            this.childCallbacks = new Dictionary<string, AppendChildData>();
            this.BuildChildCallbacks();
        }
#endregion

        #region Abstract Methods

        protected abstract void BuildChildCallbacks();
        public abstract override T FindBy(object key);
        protected abstract override void PersistNewItem(T item);
        protected abstract override void PersistUpdatedItem(T item);
        protected abstract override void PersistDeletedItem(T item);

        #endregion

        #region Properties

        protected Database Database
        {
            get { return this.database; }
        }

        protected Dictionary<string, AppendChildData> ChildCallbacks
        {
            get { return this.childCallbacks; }
        }

        #endregion

        #region Protected Methods

        protected IDataReader ExecuteReader(string sql)
        {
            DbCommand command = this.database.GetSqlStringCommand(sql);
            return this.database.ExecuteReader(command);
        }

        protected virtual T BuildEntityFromSql(string sql)
        {
            T entity = default(T);
            using (IDataReader reader = this.ExecuteReader(sql))
            {
                if (reader.Read())
                {
                    entity = this.BuildEntityFromReader(reader);
                }
            }
            return entity;
        }

        protected virtual T BuildEntityFromReader(IDataReader reader)
        {
            T entity = this.entityFactory.BuildEntity(reader);
            if (this.childCallbacks != null && this.childCallbacks.Count > 0)
            {
                object childKeyValue = null;
                DataTable columnData = reader.GetSchemaTable();
                foreach (string childKeyName in this.childCallbacks.Keys)
{
                    if (DataHelper.ReaderContainsColumnName(columnData,
                        childKeyName))
                    {
                        childKeyValue = reader[childKeyName];
                    }
                    else
                    {
                        childKeyValue = null;
                    }
                    this.childCallbacks[childKeyName](entity, childKeyValue);
                }
            }
            return entity;
        }

        protected virtual List<T> BuildEntitiesFromSql(string sql)
        {
            List<T> entities = new List<T>();
            using (IDataReader reader = this.ExecuteReader(sql))
            {
                while (reader.Read())
                {
                    entities.Add(this.BuildEntityFromReader(reader));
                }
            }
            return entities;
        }

        #endregion
    }
}

The class inherits from RepositoryBase<T> and does not implement any of its abstract methods; it simply overrides them and passes them on as abstract again. The real value it adds is in all of its protected methods to get data in and out of the local SQL CE database. One of the most interesting things about this class is that it is delegating out to a factory for building domain entity objects (EntityBase) from IDataReader instances.

When looking at the constructors, the first thing to notice is that I am using the Microsoft Enterprise Library 3.0 for data access, hence the use of the library's abstract Database class and its DatabaseFactory to create the Database class instance from configuration.

#region Constructors

        protected SqlCeRepositoryBase()
            : this(null)
        {
        }

        protected SqlCeRepositoryBase(IUnitOfWork unitOfWork)
       : base(unitOfWork)
{
            this.database = DatabaseFactory.CreateDatabase();
            this.entityFactory = EntityFactoryBuilder.BuildFactory<T>();
            this.childCallbacks = new Dictionary<string,
                                      SqlCeRepositoryBase<T>.AppendChildData>();
            this.BuildChildCallbacks();
        }

        #endregion

When doing this I actually get a SqlCeDatabase instance, which is the Enterprise Library's nice encapsulation of common actions with a SQL Server CE database. The next item of interest is the instantiation of the IEntityFactory<T> interface instance; I will discuss the purpose of that interface in the next section of this chapter. The last thing the constructor does is delegate to its derived class and call its abstract method BuildChildCallbacks. This method initializes the private Dictionary<string, AppendChildData> childCallbacks member and represents a key-value pair of the name of a field in an IDataReader instance and a delegate of type AppendChildData(T entityAggregate, object childEntityKeyValue). This will be talked about later, but it is used for allowing the SqlCeRepository<T> base class to call the method encapsulated in the delegate in order to help populate an aggregate object with data from another query in addition to the main query's results. It is very flexible in that it allows the derived class to use the base class's code for retrieving an entity, yet still leaves the door open for the derived class to append data on to the entity created by the base class.

The next section of code defines all of the abstract methods of the class:

#region Abstract Methods

        protected abstract void BuildChildCallbacks();
        public abstract override T FindBy(object key);
        protected abstract override void PersistNewItem(T item);
        protected abstract override void PersistUpdatedItem(T item);
        protected abstract override void PersistDeletedItem(T item);

        #endregion

The BuildChildCallbacks method was just discussed, and it really is optional for the derived classes to put working code into it. What I mean by that is that the derived classes must implement the method signature, but they may decide to leave the body of the method blank if the derived class does not have a need for any methods to be called back when building its entities. The rest of the methods are just passing on the strongly typed Unit of Work methods defined on the RepositoryBase<T> class.

The two read-only protected properties on the class, Database and ChildCallbacks, are simply just encapsulating their respective private members. The next four protected methods are really the heart of the class. The first method, ExecuteReader, shown below, simply takes a SQL string and executes against the SQL CE database and returns an IDataReader instance.

protected IDataReader ExecuteReader (string sql)
        {
            DbCommand command = this.database.GetSqlStringCommand(sql);
            return this.database.ExecuteReader(command);
        }

The next method, BuildEntityFromSql, uses the ExecuteReader method to help build an entity instance from a SQL statement.

protected virtual T BuildEntityFromSql(string sql)
{
   T entity = default(T);
   using (IDataReader reader = this.ExecuteReader(sql))
   {
       if (reader.Read())
       {
           entity = this.BuildEntityFromReader(reader);
       }
   }
   return entity;
}

It starts off by first getting an IDataReader from the ExecuteReader method, and then uses that IDataReader and passes it to the main method, BuildEntityFromReader, to build the entity. The Generic entity instance that is returned is a derivative of the EntityBase type.

The BuildEntityFromReader method is a little bit more complicated than the other methods in the class.

protected virtual T BuildEntityFromReader(IDataReader reader)
        {
            T entity = this.entityFactory.BuildEntity(reader);
            if (this.childCallbacks != null && this.childCallbacks.Count > 0)
            {
                object childKeyValue = null;
                DataTable columnData = reader.GetSchemaTable();
                foreach (string childKeyName in this.childCallbacks.Keys)
                {
                    if (DataHelper.ReaderContainsColumnName(columnData,
                        childKeyName))
                    {
                        childKeyValue = reader[childKeyName];
                    }
                    else
                    {
                        childKeyValue = null;
                    }
                    this.childCallbacks[childKeyName](entity, childKeyValue);
                }
            }
            return entity;
        }

It starts by delegating to the class's IEntityFactory<T> instance to build and map an entity from an IDataReader. I will discuss this Entity Factory Framework in the next section. It then checks the dictionary of child callback delegates (Dictionary<string, AppendChildData> childCallbacks) defined in the derived class to see whether any callback delegates have been defined. If there are some entries present in the dictionary, it iterates through the keys of the collection, which are really database foreign key field names from the derived class's main query. While iterating, it uses the DataHelper class to check to see whether the field name actually exists in the IDataReader's set of fields (I will discuss the DataHelper class in the next paragraph). If it does exist, it then retrieves the value of the field name from the IDataReader instance. Once that foreign key value has been extracted, it then passes the value back to the callback method, along with the partially populated entity object, and executes the method, thus filling another part of the entity object. This is particularly useful for populating aggregate objects with many child objects attached to them.

The DataHelper class is used by the various Repositories and Factories to get data to and from ADO.NET objects, such as the IDataReader. In the code example above, I was using the DataHelper's ReaderContainsColumnName method to determine whether a particular column name (or field name) existed in the DataReader's set of data. Here is the method:

public static bool ReaderContainsColumnName(DataTable schemaTable,
            string columnName)
        {
            bool containsColumnName = false;
            foreach (DataRow row in schemaTable.Rows)
            {
                if (row["ColumnName"].ToString() == columnName)
                {
                    containsColumnName = true;
                    break;
                }
            }
            return containsColumnName;
        }

The next method, BuildEntitiesFromSql, is very similar to BuildEntityFromSql, except that instead of just returning a single entity instance, it returns a generic list (IList<T>) of them.

protected virtual List<T> BuildEntitiesFromSql(string sql)
        {
            List<T> entities = new List<T>();
            using (IDataReader reader = this.ExecuteReader(sql))
            {
                while (reader.Read())
                {
                    entities.Add(this.BuildEntityFromReader(reader));
                }
            }
            return entities;
        }

The method starts by initializing the list of entities to be returned, and then similarly to BuildEntityFromSql, it calls the class's ExecuteReader method to get an IDataReader instance from the SQL statement passed in. It then iterates over the IDataReader instance and uses the BuildEntityFromReader method to build the entity and add it to its list.

The Entity Factory Framework

When I was originally building this application, I had hoped to be using the ADO.NET Entity Framework as my object-relational (OR) mapping solution. Since it was pulled from the Visual Studio 2008 release, I have decided to roll my own pseudo-mapping factory type of framework.

The IEntityFactory<T> Interface

The main concept of what I need the framework to do is extremely simple: to map field names contained in an instance of an IDataReader to fields of an object instance. Actually, it's really just mapping field names to class property names. To promote the simplicity of what I wanted, I created an interface, IEntityFactory<T>, to show my intent.

using System;
using SmartCA.Infrastructure.DomainBase;
using System.Data;

namespace SmartCA.Infrastructure.EntityFactoryFramework
{
    public interface IEntityFactory<T> where T: EntityBase
    {
        T BuildEntity(IDataReader reader);
    }
}

This interface is extremely simple, its one method, BuildEntity, takes an IDataReader and returns an object that derives from EntityBase. Now, since I have this interface in place, I need to have a way of figuring out how to get the right object instances of this interface. I will use a factory class to do this, named EntityFactoryBuilder.

Configuration Section

Just like the RepositoryFactory, I have chosen to use configuration along with my EntityFactoryBuilder. This keeps things very flexible.

Here is what the application configuration file with added support for the Entity Factory Framework looks like:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary
.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=null"/>
 <section name="repositoryMappingsConfiguration"

type="SmartCA.Infrastructure.RepositoryFramework.Configuration
.RepositorySettings, SmartCA.Infrastructure, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null"/>
 <section name="entityMappingsConfiguration"

type="SmartCA.Infrastructure.EntityFactoryFramework.Configuration
.EntitySettings,
SmartCA.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </configSections>
    <dataConfiguration defaultDatabase="SmartCA"/>

    <connectionStrings>
<add name="SmartCA" connectionString="Data Source=|DataDirectory|SmartCA.sdf"
        providerName="System.Data.SqlServerCe.3.5"/>
  </connectionStrings>

  <repositoryMappingsConfiguration>
    <repositoryMappings>
      <repositoryMapping interfaceShortTypeName="IProjecTRepository"

   repositoryFullTypeName="SmartCA.Infrastructure.Repositories.ProjecTRepository,
   SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
   PublicKeyToken=null" />
      <repositoryMapping interfaceShortTypeName="IEmployeeRepository"

   repositoryFullTypeName="SmartCA.Infrastructure.Repositories.EmployeeRepository,
   SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
   PublicKeyToken=null" />
      <repositoryMapping interfaceShortTypeName="ICompanyRepository"

   repositoryFullTypeName="SmartCA.Infrastructure.Repositories.CompanyRepository,
   SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
   PublicKeyToken=null" />
      <repositoryMapping interfaceShortTypeName="IContacTRepository"

   repositoryFullTypeName="SmartCA.Infrastructure.Repositories.ContacTRepository,
   SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
   PublicKeyToken=null" />
    </repositoryMappings>
  </repositoryMappingsConfiguration>

  <entityMappingsConfiguration>
    <entityMappings>
      <entityMapping entityShortTypeName="Project"

entityFactoryFullTypeName="SmartCA.Infrastructure.Repositories.ProjectFactory,
SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" />
      <entityMapping entityShortTypeName="Employee"

entityFactoryFullTypeName="SmartCA.Infrastructure.Repositories.EmployeeFactory,
SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" />
      <entityMapping entityShortTypeName="Company"

entityFactoryFullTypeName="SmartCA.Infrastructure.Repositories.CompanyFactory,
SmartCA.Infrastructure.Repositories, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" />
   </entityMappings>
</entityMappingsConfiguration>

</configuration>

Configuration Section Handling

Again, just as with the Repository Framework configuration, I have added a Configuration folder under the EntityFactoryFramework folder of the SmartCA.Infrastructure project (see Figure 2.4).

EntityFactoryFramework Configuration folder.

Figure 2.4. EntityFactoryFramework Configuration folder.

I am not going to show the configuration code for the Entity Factory Framework because it is almost exactly the same as the configuration code for the Repository Framework.

The EntityFactoryBuilder Class

Now that the configuration is finished, the EntityFactoryBuilder can use it to create repositories. The way the EntityFactoryBuilder works is that it uses a Generic type parameter representing the type of the entity that needs to be mapped, combined with the mappings from the configuration in order to determine what kind of IEntityFactory<T> to create. The EntityFactoryBuilder class is a static class with one static method, BuildFactory.

using System;
using System.Collections.Generic;
using SmartCA.Infrastructure.DomainBase;
using SmartCA.Infrastructure.EntityFactoryFramework.Configuration;
using System.Configuration;

namespace SmartCA.Infrastructure.EntityFactoryFramework
{
    public static class EntityFactoryBuilder
    {
        // Dictionary used for caching purposes
        private static Dictionary<string, object> factories =
            new Dictionary<string, object>();

        public static IEntityFactory<T> BuildFactory<T>() whereT: EntityBase
        {
            IEntityFactory<T> factory = null;

            // Get the key from the Generic parameter passed in
            string key = typeof(T).Name;
// See if the factory is in the cache
            if (EntityFactoryBuilder.factories.ContainsKey(key))
            {
                // It was there, so retrieve it from the cache
                factory = EntityFactoryBuilder.factories[key] as IEntityFactory<T>;
            }
            else
            {
                // Create the factory

                // Get the entityMappingsConfiguration config section
EntitySettings settings = (EntitySettings)ConfigurationManager.GetSection
(EntityMappingConstants.EntityMappingsConfigurationSectionName);

                // Get the type to be created using reflection
                Type entityFactoryType =
Type.GetType(settings.EntityMappings[key].EntityFactoryFullTypeName);

                // Create the factory using reflection
                factory = Activator.CreateInstance(entityFactoryType) as
IEntityFactory<T>;

                // Put the newly created factory in the cache
                EntityFactoryBuilder.factories[key] = factory;
            }

            // Return the factory
            return factory;
        }
    }
}

The signature of this method is much simpler than the RepositoryFactory class's GeTRepository<TRepository, TEntity> method. It has only one Generic type parameter, T, and that is the type of entity for which the factory was created. The T parameter has a restriction that it must be derived from the EntityBase class.

First, the code for the method uses .NET Reflection to find the short type name of the Generic parameter type being passed in via the T parameter. Then, the code looks in its static dictionary of entity factories to see whether it can pull the particular Factory out of memory. If it cannot, it then uses the custom Entity Factory Framework configuration objects to find the right entity factory type to create based on the values in the mappings configuration. When the type is found, the method then uses the reflection capabilities of the Activator object to create an instance of the correct Factory based on the mapped type from configuration. Then, after the Factory has been created, it is put into the static dictionary of repositories so it will be available the next time it has been requested. Once the Factory has been retrieved from memory or created, the instance is then returned to the caller.

The Model-View-ViewModel Pattern

Traditional Presentation Patterns

So far, I have covered the various patterns and principles being followed in the domain layer and the infrastructure layer. Since this book is about Domain-Driven Design, that is a good thing, but I still have an application to build; it cannot just be all domain objects and unit tests. I actually have to make the application present something fairly compelling to the user. If you remember, in Chapter 1 I stated that I was going to be using WPF for the presentation technology. That is all well and good, but there must be some type of strategy for hooking up domain objects to the user interface. Some very common presentation patterns are the Model-View-Controller (MVC) and the Model-View-Presenter (MVP). These patterns are very good, and I highly encourage you to study more about them; however, in my opinion, they have one major drawback when used with WPF: they do not take into account data-binding technology at all. What I mean by that, is that in those patterns, the Controller or the Presenter is responsible for acting upon the View, such as filling TextBoxes with text, loading ListBoxes, filling a grid, and so on. It just so happens that one of WPF's greatest strengths is its rich data-binding capabilities. By implementing either the MVC or the MVP pattern, I would be completely bypassing the data-binding facilities in WPF. There must be some way to make this concept of separating the View from the Model work in WPF without bypassing a whole slew of rich WPF features!

Model-View-ViewModel Definition

That way is the Model-View-ViewModel pattern. I first learned about this pattern by reading John Gossman's blog entries about it. He was a member of the Microsoft Expression Blend team and is currently on the WPF team at Microsoft. In his blog entries, he talks about how his team has created this new pattern, called Model-View-ViewModel, to separate the Model from the View but, at the same time, to take full advantage of WPF's features. According to John "The pattern was to take a pure Model, create an abstract view that contained state, and data bind a View created with a visual designer to that abstract view. That's a nice clean, formal pattern." In this case, the visual designer is the Microsoft Expression Blend tool, and the abstract view is the ViewModel. The key point is that there is a two-way connection between the View and the ViewModel via data binding. When properly set up, this means that every View will consist of almost nothing but pure XAML and very little procedural code, which is exactly what I want.

Because this pattern separates out the View and the Model so nicely, there are a lot of opportunities for graphic artist types to work in Blend all day, hand the XAML off to a developer working on the domain model, and have the developer wire everything up to the domain model. Shortly, I will show how I implemented this pattern for the SmartCA application.

What's a ViewModel?

You must be asking yourself this question by now. When I first read about it and looked at some sample code, it took me a while to grasp the full power of it. The purpose in life for a ViewModel is to adapt the Model to the View. This may mean that you have a method in the domain model that returns an IList<Project> type, but you would really like to convert that into a more WPF-friendly class for data binding purposes. Enter the ViewModel. In this case the ViewModel would transform the IList<Project> type from the domain model into something like a CollectionView class for a WPF UI Element to bind data to. The key is to expose public properties on the ViewModel for the things that the View needs to bind data to. Also, like a Controller, the ViewModel can be used to hold the View's state, as well as any commands that the View needs.

Since WPF natively implements the Command pattern, by which I mean certain UI elements such as Button controls, there is a property called Command that is of the WPF-defined ICommand type. I can place Commands into my ViewModel and expose them as public properties for my View to bind to. This is extremely powerful, as it allows me to bind executable code to a Button on a form without having to write any code to wire up the Button. WPF's Command pattern along with a public Command property on my ViewModel take care of this.

An Example

In order to understand this a little better, I will show you a part of the SmartCA application. The use case is extremely simple; it is to display a form to the user to show a list of projects, and have the user pick a project, and remember what project was selected. The selected project is what the user will be working on in his or her session until the user decides to change to another project. Since the point of this example is the Model-View-ViewModel presentation pattern, I will focus a little bit less on the domain and a little bit more on the presentation items.

To start off with, I first create a Service class in my domain model, called ProjectService. ProjectService has one method we care about right now, and that is GetProjects.

using System;
using System.Collections.Generic;
using SmartCA.Model.Projects;
using SmartCA.Infrastructure.RepositoryFramework;

namespace SmartCA.Model.Projects
{
    public static class ProjectService
    {
        public static IList<Project> GetAllProjects()
        {
            IProjecTRepository repository =
RepositoryFactory.GeTRepository<IProjecTRepository, Project>();
            return repository.FindAll();
        }
    }
}

The code is pretty straightforward; it is simply acting as a façade to the IProjecTRepository instance and gets a list of all of the repository's Projects. So far so good; I now have a way of getting the data that I need.

The next step is to build a View for displaying the list of Projects to the user in the form of a dropdown list. Figure 2.5 shows what I want the form to look like.

The SelectProjectView view

Figure 2.5. The SelectProjectView view

In order to get to this point, I need to build a ViewModel class that I can have the SelectProjectView class bind to. I only need to expose a list and two commands, one per button.

using System;
using System.Collections.Generic;
using SmartCA.Model.Projects;
using System.Windows.Data;
using SmartCA.Infrastructure.UI;
using SmartCA.Presentation.Views;
using SmartCA.Application;

namespace SmartCA.Presentation.ViewModels
{
    public class SelectProjectViewModel
    {
        private CollectionView projects;
        private DelegateCommand selectCommand;
        private DelegateCommand cancelCommand;
        private IView view;

        public SelectProjectViewModel()
            : this(null)
        {
        }

        public SelectProjectViewModel(IView view)
        {
            this.view = view;
            this.projects = new CollectionView(ProjectService.GetAllProjects());
            this.selectCommand = new DelegateCommand(this.SelectCommandHandler);
            this.cancelCommand = new DelegateCommand(this.CancelCommandHandler);
        }

        public CollectionView Projects
        {
            get { return this.projects; }
        }

        public DelegateCommand SelectCommand
        {
            get { return this.selectCommand; }
        }

        public DelegateCommand CancelCommand
        {
            get { return this.cancelCommand; }
        }

        private void SelectCommandHandler(object sender, EventArgs e)
        {
            Project project = this.projects.CurrentItem as Project;
            UserSession.CurrentProject = project;
            this.view.Close();
        }
private void CancelCommandHandler(object sender, EventArgs e)
        {
            this.view.Close();
        }
    }
}

The first thing to note about this class is its overloaded constructor. It first gives a reference to the View via the IView interface. This interface currently has two methods, Show and Close, and it just so happens that the WPF Window class happens to implement both of these methods.

using System;

namespace SmartCA.Presentation.Views
{
    public interface IView
    {
        void Show();
        void Close();
    }
}

This interface allows me to open and close the form from my ViewModel.

The next thing that the SelectProjectViewModel constructor does is to transform the IList<Project> list of projects into a WPF-friendly CollectionView class. This CollectionView is then exposed via the Projects public property.

public SelectProjectViewModel(IView view)
        {
            this.view = view;
            this.projects = new CollectionView(ProjectService.GetAllProjects());
            this.selectCommand = new DelegateCommand(this.SelectCommandHandler);
            this.cancelCommand = new DelegateCommand(this.CancelCommandHandler);
        }

The next two lines are interesting not in that they are setting up the two ICommand properties for the two Buttons, but rather that they are using a class called DelegateCommand to represent the ICommand instances. The DelegateCommand class not only implements the ICommand interface but also allows a delegate to be called when the ICommand's Execute method is called.

using System;
using System.Windows.Input;

namespace SmartCA.Infrastructure.UI
{
    public class DelegateCommand: ICommand
    {
        public delegate void SimpleEventHandler(object sender, EventArgs e);

        private SimpleEventHandler handler;
        private bool isEnabled = true;
public DelegateCommand(SimpleEventHandler handler)
        {
            this.handler = handler;
        }

        #region ICommand implementation

        /// <summary>
        /// Executing the command is as simple as calling that method
        /// we were handed on creation.
        /// </summary>
        /// <param name="parameter">Data used by the command. If the
        /// command does not require data to be passed,
        /// this object can be set to null.</param>
        public void Execute(object parameter)
        {
            this.handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Determines whether the command can execute in its
        /// current state.
        /// </summary>
        /// <param name="parameter">Data used by the command. If the
        /// command does not require data to be passed,
        /// this object can be set to null.</param>
        /// <returns>True if the command can be executed.</returns>
        public bool CanExecute(object parameter)
        {
            return this.IsEnabled;
        }

        /// <summary>
        /// This is the event that WPF's command architecture listens to so
        /// it knows when to update the UI on command enable/disable.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        #endregion

        /// <summary>
        /// Public visibility of the isEnabled flag—note that when it is
        /// set, need to raise the event so that WPF knows to update
        /// any UI that uses this command.
        /// </summary>
        public bool IsEnabled
        {
            get { return this.isEnabled; }
            set
            {
                this.isEnabled = value;
                this.OnCanExecuteChanged();
}
        }

        /// <summary>
        /// Simple event propagation that makes sure someone is
        /// listening to the event before raising it.
        /// </summary>
        private void OnCanExecuteChanged()
        {
            if (this.CanExecuteChanged != null)
            {
                this.CanExecuteChanged(this, EventArgs.Empty);
            }
        }
    }
}

As advertised, the real power of this class is that, when its Execute method is called, it calls the delegate method that was passed in via the constructor. The reason why this is so powerful is that I can define the method handler for the delegate right inside of my ViewModel class, which keeps all of the presentation logic glue right where I want it.

So going back to the SelectProjectViewModel class, here are the handler methods for the two DelegateCommand properties.

private void SelectCommandHandler(object sender, EventArgs e)
        {
            Project project = this.projects.CurrentItem as Project;
            UserSession.CurrentProject = project;
            this.view.Close();
        }

        private void CancelCommandHandler(object sender, EventArgs e)
        {
            this.view.Close();
        }

The handler for the SelectCommand property is a true example of why the ViewModel shines. Instead of having to talk to an element on the UI to know which project was selected, it simply asks the CollectionView for its CurrentItem property to get the selected project. This is made possible by the default two-way binding in the XAML, which I will show shortly. The handler method then sets the CurrentProject property of the application layer's UserSession class. Then, since its work is done, it tells the View to go away via the Close method of the IView interface.

The handler for the CancelCommand property is much simpler. It simply tells the View to close itself via the IView interface.

Now that the ViewModel class for the use case SelectProjectViewModel has been detailed, it's time to look at how the View actually uses it and communicates with it. The View class, SelectProjectView, has very little code behind in it. The only code that I wrote for it was in the constructor for wiring up the DataContext property of the form's Window element.

using System;
using System.Windows;
using System.Windows.Controls;
using SmartCA.Presentation.ViewModels;

namespace SmartCA.Presentation.Views
{
    public partial class SelectProjectView: Window, IView
    {
        public SelectProjectView()
        {
            this.InitializeComponent();
            this.DataContext = new SelectProjectViewModel(this);
        }
    }
}

The first thing to notice is that I added the implementation of the IView interface to the class. This was easy since the System.Windows.Window class already implemented the Close and Show methods. Then, in the constructor, after the auto-generated call to InitializeComponent, I set the Window's DataContext property to the SelectProjectViewModel class, passing in the Window instance (this) as the IView instance expected in SelectProjectViewModel's constructor. Finally, the form is wired up for data binding to the ViewModel.

The XAML markup for the View contains the ComboBox declaration, a few Label declarations, as well as a few Button declarations.

<Window x:Class="SmartCA.Presentation.Views.SelectProjectView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:SmartCA.Presentation.ViewModels"
    Title="SelectProjectView" Height="300" Width="437"
    Background="{DynamicResource FormBackgroundBrush}">
    <Grid>
    <ComboBox  Height="26" Margin="175.993333333333,98,28.006666666667,0"
         Name="projectsComboBox" VerticalAlignment="Top"
         IsSynchronizedWithCurrentItem="True"
         TextSearch.TextPath="Name"
         ItemsSource="{Binding Path=Projects}" IsTextSearchEnabled="True"
         IsEditable="True">
         <ComboBox.ItemTemplate>
                <DataTemplate>
                       <Grid ShowGridLines="True" >
                              <Grid.ColumnDefinitions>
                                     <ColumnDefinition Width="50" />
                                     <ColumnDefinition />
                              </Grid.ColumnDefinitions>
                              <TextBlock Grid.Column="0" Text="{Binding
Path=Number}"/>
                              <TextBlock Grid.Column="1" Text="{Binding Path=Name}" />
                       </Grid>
                </DataTemplate>
<ComboBox.ItemTemplate>
    </ComboBox>
    <Label Margin="47,42,0,0" Name="selectProjectLabel"
         Style="{StaticResource boldLabelStyle}"
         VerticalAlignment="Top" HorizontalAlignment="Left"
         Width="153">Please select a Project.</Label>
    <Label Margin="47,98.04,0,0" Name="projectLabel"
         Style="{StaticResource boldLabelStyle}">Project:</Label>
    <Button Margin="47,0,0,35" Name="cancelButton"
         Command="{Binding Path=CancelCommand}" Style="{StaticResource baseButton}"
         HorizontalAlignment="Left" VerticalAlignment="Bottom">Cancel</Button>
    <Button Margin="0,0,28.006666666667,35" Name="okButton"
         Command="{Binding Path=SelectCommand}" Style="{StaticResource baseButton}"
         HorizontalAlignment="Right" VerticalAlignment="Bottom">OK</Button>
  </Grid>
</Window>

The first interesting thing to note about the ComboBox declaration is that it is bound to the Projects CollectionView property of the SelectProjectViewModel, and that its IsSynchronizedWithCurrentItem property is set to True. What this means is that whenever I change a selection in the ComboBox, I can always get the item selected from the CollectionView in the ViewModel to which it is bound, in this case the Projects property. The way I get that is by checking the SelectedItem property of that CollectionView. That is cool because I do not need to be tightly coupled to the UI elements in the ViewModel; data binding takes care of giving me the state that I need.

The next interesting thing about the ComboBox declaration is its use of a DataTemplate element to format how the dropdown will be displayed. In this case, the dropdown will show two columns instead of one, and each one of the columns is bound to properties of the child Property objects via the Path property of the Binding declaration. What's nice about using this pattern is that I can make the code for the UI View be more declarative, that is, keep most of it in XAML, and really get a good separation between the View and the Model, while at the same time take advantage of WPF's binding features to reduce the amount of code that I would have had to write to do this manually.

Summary

I covered quite a bit of ground in this chapter. I started out by designing the Visual Studio solution that will be used throughout the rest of the book, and then began the design for the four architectural layers, which were the application, domain, infrastructure, and presentation layers. In designing and implementing the layers, I introduced a few patterns that will be used throughout the book, such as the Layered Supertype pattern, the Separated Interface pattern, and the Model-View-ViewModel pattern. Also, when talking about the domain layer, I covered some very important Domain-Driven Design terms, which will be used throughout the remainder of the book.

I also wrote some code in this chapter! I started writing code for the infrastructure layer with the Layered Supertype implementation, followed by the Repository Framework and the Entity Factory Framework, and ending with the Model-View-ViewModel pattern implementation for the presentation layer. Overall, there is a good foundation on which to build for the rest of the application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.185.170