tech·nic·al·ly agile

Creating a Data Access layer using Unity

Learn to create a robust Data Access layer using Unity for efficient dependency injection and mapping. Simplify your coding process with expert insights!

Published on
6 minute read
Image
https://nkdagility.com/resources/ChjJ40t-403

I am always pulling out the Unity assemblies. Maybe it is just because I am lazy, but I really can’t be bothered rolling my own dependency injection and mapping framework!

Creating a Data Access layer using Unity

I am going to use Unity only as a mapping frame work for now, I want to be able to pass an Interface into a method, and get back the correct data access class.

The plan is to meet the diagram on the left. Only the factory and the interfaces are accessible, but are all set to “friend” which will require an assembly tag to be added to both the Factory and the Interfaces assemblies to allow explicit access.

1<Assembly: InternalsVisibleTo("Hinshlabs.TfsDynamicPolicy.Services.Server")>

This allows classes in the named assembly to access all classes and methods that have been prefaced with the “Friend” access level. Its a sneaky way of helping to maintain your layer integrity. So with this reference added only the Services.Server assembly, the one with the web service implementation, can access the factory and the interfaces, making them un-callable from any other assembly.

note: if you use only the assembly’s friendly name and not the explicit signed name then someone could just create an assembly of the same name as above and they will be able to call as if they were Services.Server. This is not to prevent hacking, just those pesky developers (me) who may try to bypass the service tier…

If, like me you are running tests you will also need to add an InternalsVisibleTo entry for your test assemblies or you will be plagued by “Assessors”..

First is my IDataAccess class, this is really only exists so there is some validation on my generics.

Creating a Data Access layer using Unity  

1' Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess.Common
2Public Interface IDataAccess
3
4End Interface

I also have a more specific Interface that allows for the loading of Artefacts. I have not yet implemented anything more than get and add, but you can see that it inherits (yes an interface and inherits in the same sentence) from the IDataAccess interface so we can pass it as a generic type that complies with IDataAccess.

 1'Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess.Common
 2Imports Hinshlabs.TfsDynamicPolicy.Common
 3
 4Public Interface IArtifactDataAccess(Of T As Artifact)
 5    Inherits IDataAccess
 6
 7    Function GetArtifact(ByVal id As Guid) As T
 8    Function GetArtifact(ByVal Uri As Uri) As T
 9    Function GetArtifacts() As ArtifactCollection
10    Function AddArtifact(ByVal artifact As T) As Boolean
11
12End Interface

Wow… that was hard, IDataAccess may have a little more than nothing in the future, but for now that is it. Now, what I need is a class that I can inherit from that will provide the functionality I need for any factory. This is mainly coz factories bread factories.

Creating a Data Access layer using Unity

 1'Assembly: Hinshlabs.TfsDynamicPolicy.Common
 2Imports System.IO
 3Imports System.Globalization
 4Imports System.Xml.Serialization
 5Imports System.Configuration
 6Imports Microsoft.Practices.Unity
 7Imports Microsoft.Practices.Unity.Configuration
 8Imports Hinshlabs.TfsDynamicPolicy.Common
 9Imports System.Reflection
10
11Friend MustInherit Class UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)})
12
13#Region " Singleton"
14
15    Private Shared m_Instance As T
16
17    Friend Shared ReadOnly Property Instance As T
18        Get
19            If m_Instance Is Nothing Then
20                m_Instance = New T
21                m_Instance.Initialize()
22            End If
23            Return m_Instance
24        End Get
25    End Property
26
27    Protected Sub New()
28        ' Do nothing in here
29    End Sub
30
31#End Region
32
33    Private m_UnityContainer As IUnityContainer
34
35    Private Sub Initialize()
36        ' Create Unity container
37        m_UnityContainer = New UnityContainer()
38        ' Configure Unity
39        Dim config As Configuration
40        Dim fm As New ExeConfigurationFileMap
41
42        fm.ExeConfigFilename = ConfigFilename
43        Dim configFileLocation As String = Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly.Location), ConfigFilename)
44        If Not File.Exists(configFileLocation) Then
45            Throw New FileNotFoundException(String.Format(CultureInfo.InvariantCulture, "Unable to load config file with the name {0}", fm.ExeConfigFilename), configFileLocation)
46        End If
47        config = ConfigurationManager.OpenMappedExeConfiguration(fm, ConfigurationUserLevel.None)
48        Dim section As UnityConfigurationSection = CType(config.GetSection("unity"), UnityConfigurationSection)
49        If section Is Nothing Then
50            Throw New AccessViolationException(String.Format(CultureInfo.InvariantCulture, "There is no unity section called {0} in the config file {1}", UnityContainerName, ConfigFilename))
51        End If
52        section.Containers(UnityContainerName).Configure(m_UnityContainer)
53    End Sub
54
55    Protected ReadOnly Property UnityContainer As IUnityContainer
56        Get
57            Return m_UnityContainer
58        End Get
59    End Property
60
61    Protected MustOverride ReadOnly Property UnityContainerName As String
62    Protected MustOverride ReadOnly Property ConfigFilename As String
63
64End Class

The UnityFactoryBase class provides a couple of features. It provides a Singleton pattern so that we make sure that there is only ever one instance per factory type T and we initialise a UnityContainer for each Instance of factory T. You can see that on the class definition the generic type T that will be passed in is of the same type as the class itself. This makes sure that the class that represents T inherits from UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)}). When configuring the Unity Container we get both the container name and the config file to load from the child class. This allows for both different config files per factory and the option to have a single config file and multiple unity configuration elements. Its up to you…

We need to inherit from UnityFactoryBase(Of T As {New, UnityFactoryBase(Of T)})  to create our factory and provide a config file to configure the UnityContainer. The inherited class is pretty simple as we have done most of the heavy lifting in the base class.

Creating a Data Access layer using Unity

 1Imports Hinshlabs.TfsDynamicPolicy.DataAccess.Common
 2' Assembly: Hinshlabs.TfsDynamicPolicy.DataAccess
 3Imports Hinshlabs.TfsDynamicPolicy.Common
 4Imports System.Globalization
 5
 6Friend Class DataAccessFactory
 7    Inherits UnityFactoryBase(Of DataAccessFactory)
 8
 9    Public Sub New()
10        ' Do nothing in here
11    End Sub
12
13    Protected Overrides ReadOnly Property UnityContainerName As String
14        Get
15            Return "DataAccess"
16        End Get
17    End Property
18
19    Protected Overrides ReadOnly Property ConfigFilename As String
20        Get
21            Return String.Format(CultureInfo.InvariantCulture, "{0}.Unity.config", System.Reflection.Assembly.GetExecutingAssembly().GetName.Name)
22        End Get
23    End Property
24
25    Public Function GetDataAccess(Of T As IDataAccess)() As T
26        Return UnityContainer.Resolve(Of T)()
27    End Function
28
29End Class

The DataAccessFactory provides the data needed by the UnityFactoryBase(Of DataAccessFactory) as well as the method that I need to retrieve an IDataAccess class. I will show you how it is called, but first there is the little matter of config:

 1<?xml version="1.0" encoding="utf-8" ?>
 2<configuration>
 3  <configSections>
 4    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
 5  </configSections>
 6  <unity>
 7    <typeAliases>
 8      <!-- Lifetime manager types should be inserted if you need lifetime managers -->
 9      <typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
10      <typeAlias alias="external" type="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager, Microsoft.Practices.Unity" />
11      <!-- User defined type aliases -->
12      <!-- An interface for artifact data access implementation -->
13      <typeAlias alias="IArtifactDataAccess`1" type="Hinshlabs.TfsDynamicPolicy.DataAccess.Common.IArtifactDataAccess`1, Hinshlabs.TfsDynamicPolicy.DataAccess.Common" />
14    </typeAliases>
15    <containers>
16      <container name="DataAccess">
17        <types>
18          <!-- Lifetime managers specified using the type aliases -->
19          <type type="IArtifactDataAccess`1" mapTo="Hinshlabs.TfsDynamicPolicy.DataAccess.Xml.ArtifactDataAccess`1, Hinshlabs.TfsDynamicPolicy.DataAccess.Xml">
20            <lifetime type="singleton" />
21          </type>
22        </types>
23      </container>
24    </containers>
25  </unity>
26</configuration>

I am not going to explain the config file as it is well (ish) documented, but it effectively mapped all generic calls to retrieve IArtifactDataAccess`1 to the implementation in the XML assembly of ArtifactDataAccess`1 and makes the resultant object a singleton.

To call this lovely package after you have populated it with many many DataAccess goodies all you need to do is this:

1Dim dal As IArtifactDataAccess(Of DynamicPolicy) = DataAccessFactory.Instance.GetDataAccess(Of IArtifactDataAccess(Of DynamicPolicy))()

Lovely and simple, and to add a new implementation all I need is an Interface like IArtifactDataAccess.. lets call it IHypotheticalDataBits, a concrete implementation… lets call it HypoDataFromTwitter and a mapping in the config file:

1<type type="IHypotheticalDataBits" mapTo="Hinshlabs.TfsDynamicPolicy.DataAccess.Xml.HypoDataFromTwitter, Hinshlabs.TfsDynamicPolicy.DataAccess.Xml">
2  <lifetime type="singleton" />
3</type>

And you can then call:

1Dim dal As IHypotheticalDataBits = DataAccessFactory.Instance.GetDataAccess(Of IHypotheticalDataBits)()

Any easier and it would be writing for you :)

Technorati Tags: .NET    Developing    Version Control    CodeProject 

Software Development Technical Mastery
Comments

Related blog posts

No related videos found.

Connect with Martin Hinshelwood

If you've made it this far, it's worth connecting with our principal consultant and coach, Martin Hinshelwood, for a 30-minute 'ask me anything' call.

Our Happy Clients​

We partner with businesses across diverse industries, including finance, insurance, healthcare, pharmaceuticals, technology, engineering, transportation, hospitality, entertainment, legal, government, and military sectors.​

Emerson Process Management Logo

CR2

Workday Logo
Teleplan Logo
Cognizant Microsoft Business Group (MBG) Logo
Genus Breeding Ltd Logo
Big Data for Humans Logo
Boeing Logo
Lean SA Logo
ProgramUtvikling Logo
SuperControl Logo
Slicedbread Logo
Healthgrades Logo
Boxit Document Solutions Logo
Freadom Logo
New Signature Logo
Deliotte Logo
Alignment Healthcare Logo
Royal Air Force Logo
Department of Work and Pensions (UK) Logo
Washington Department of Transport Logo
Ghana Police Service Logo
Nottingham County Council Logo
New Hampshire Supreme Court Logo
Microsoft Logo
Big Data for Humans Logo
Healthgrades Logo
New Signature Logo
Ericson Logo
Xceptor - Process and Data Automation Logo