Adaptive Access Layers

This project is the open source implementation of the runtime type factory presented in Ulrik Borns MSDN Magazine article Adaptive Access Layers + Dependency Injection = Productivity.

The core of the project is the Adaptive.Core assembly with the AdaptiveFactory class. With this, you can with very little effort write your own Adaptive Access Layer without having to care about runtime type generation or IL emit.

The factory class can implement almost any interface according to the flexible strategies you specify in clear code. This makes it easy to solve challenges like:
  • Implement a simple DTO class (optionally with with change notification via INotifyPropertyChanged)
  • Implement a simple proxy class (optionally with interception of all/selected calls)
  • Implement an access layer like the Mail Access Layer or the Database Access Layer presented in the MSDN article.

The AdaptiveFactory class itself is lightweight and it produces highly efficient runtime types. These types have no references back to the factory class and can be used in any context or even saved to a disk assembly.

Check out the Documentation page for information on how to get started using the AdaptiveFactory.

Mail Access Layer

The solution also contains a small sample MailAccessLayer implementation for sending emails. It is simple but fully functional and illustrates all of the ideas.

NLog Access Layer

The solution includes an access layer around the NLog logging framework. With this you don't need to expose any NLog types to your code and can instead define your own flexible logging interfaces around the NLog Logger class. The functionality is in the Adaptive.Log.NLog assembly.

Dapper Database Access Layer

The Dapper Database Access Layer is a thin wrapper around the Dapper ORM. The layer hides all Dapper specifics from your code and moves the SQL query strings out from your business logic into an attributes access layer interface. This improves testability and extensibility dramatically.

With plain Dapper you would access your database like this:
string query = "SELECT * FROM dbo.Accounts WHERE @accountType=AccountType";
using (IDbConnection connection = GetMyConnection())
  IEnumerable<Accounts> = connection.Query<Account>(query, new { AccountType=theAccountType });

This approach exposes the Dapper API to your business logic code and it also introduces a fairly complex syntax of the anonymous type.

With Dapper Access Layer you would instead map all your database queries to simple .NET methods in a few interfaces like this:
public interface IAccountsDb
  [Query("SELECT * FROM dbo.Accounts WHERE @accountType=AccountType")]
  IEnumerable<Account> GetAccountsByType(int accountType);

And then make the actual database call in a much simpler way:
// Get runtime type once during startup
IAccountsDb db = DapperAccessLayer.Create<IAccountsDb>(GetMyConnection);

// And then do this whenever db access is needed
IEnumerable<Accounts> accounts = db.GetAccountsByType(theAccountType);

The latter approach is simpler to read and much more testable as you easily can mock out the IAccountsDb interface.

File & Directory Access Layers

The static File and Directory classes of the .NET framework are extremely powerful and easy to use. One of the downsides of using these classes in your code is that they reduce testability as you now need to establish a proper realistic file/folder layout in order to run unit tests. The File Access Layer and Directory Access Layer solve this problem by adding an adaptive facade interface in front of these two classes. You can then code against such interfaces rather than the static classes and thereby easily mock out the file system during testing.

Last edited Sep 6, 2014 at 5:40 PM by ulrikborn, version 12