NOTE!

The content in this page is obsolete and applies to a previous version of the Commons Library. There have been some major changes recently and I have not had a chance to update this page based on that. So there.

Commons Library


This is a general purpose commons library that I've built mostly for my own use within applications that I build (but obviously you are welcome to use it should you choose). The goal is to have an easy-to-use and uniform yet modular and pluggable facility to handle common cross-cutting concerns in my applications, thereby freeing me up to focus on the actual application concerns and hopefully making it easier and faster to build them.
Installation
The library is available in Nuget as AK.Commons. You can use the Package Manager Console in Visual Studio and run Install-Package AK.Commons.
Initialization
Initialization is handled by the AK.Commons.AppEnvironment class. You initialize the application environment by calling AppEnvironment.Initialize() in your application startup routine. This is the Main method for Windows applications and Application_Start for web applications. The call requires a unique name for the application that is used, among other things, to retrieve application-specific settings from the configuration store (see Configuration), and also to include in log entries.

The second parameter is an instance of InitializationOptions that is optional, but you're almost always better off providing it. It lets you specify whether logging is enabled (if you don't enable logging and use components that expect a logger, they will fail). It also lets you specify what Configuration Store you want to use for the application (see Configuration).

The following example initializes an application using configuration store settings from a mapped EXE config file.

var config = ConfigurationManager.OpenMappedExeConfiguration(...);

AppEnvironment.Initialize("MyApplication",
	new InitializationOptions
	{
		EnableLogging = true
		ConfigStore = config.GetConfigStore(),
	});
IoC/DI/Composition
The library uses MEF for IoC/DI and composition. You can build composable modules using regular MEF exports and imports. You can access the composition interface using AppEnvironment.Composer. If you're inside a composable class, you can also just put a MEF import for the AK.Commons.Composition.IComposer interface.

It consists of a number of wrapper methods around MEF's own resolve-type methods. The scope of DLLs that are loaded in by the composer are: the entry assembly, the executing assembly, and assemblies in the location defined by the configuration key ak.commons.composition.modulesdirectories. For more on configuration keys, see Configuration.

The composition container is built by the call to AppEnvironment.Initialize().

An example of the simplest variant of dependency resolution is:

var myInstance = AppEnvironment.Composer.Resolve<MyInterface>();
Or, if you're inside a composable class:

public class MyClass
{
	[Import] private IComposer composer;
	
	public void MyMethod()
	{
		var myInstance = this.composer.Resolve<MyInterface>();
	}
}

For web applications, you can use AK.Commons.Web.Composition.ComposableDependencyResolver and AK.Commons.Web.Composition.ComposableControllerFactory to create composition-enabled MVC and Web API controllers.

Configuration
Configuration Store
A configuration store is a provider of configuration data. The library expects configuration data in .NET's configuration XML format (see more on the format below). You can implement the AK.Commons.Configuration.IConfigStore interface to implement your own configuration store. There are two built-in ones, XmlFileConfigStore and WebUrlConfigStore that use a local XML file or a web URL that serves up the configuration XML. The configuration store itself can be configured through a bootstrap configuration file. For example, the following App.config file tells the application to use the given XML file as the configuration store.

<configuration>
  <configSections>
    <section name="ak.commons.configuration.store" 
     type="AK.Commons.Configuration.Sections.StoreConfigurationSection, AK.Commons" />    
  </configSections>
  <ak.commons.configuration.store>
    <store type="AK.Commons.Providers.Configuration.XmlFileConfigStore, AK.Commons">
      <properties>
        <property name="FilePath" value="~/AppConfig.xml" />
      </properties>
    </store>
  </ak.commons.configuration.store>
</configuration>
The ak.commons.configuration.store section in the above example could be changed to the following to use a web URL instead:

  <ak.commons.configuration.store>
    <store type="AK.Commons.Providers.Configuration.WebUrlConfigStore, AK.Commons">
      <properties>
        <property name="Url" value="http://myconfig/AppConfig.xml" />
        <property name="Authenticate" value="true" />
        <property name="UseDefaultCredentials" value="false" />
        <property name="UserName" value="myuser" />
        <property name="Password" value="mypwd" />
        <property name="Domain" value="mydomain" />
      </properties>
    </store>
  </ak.commons.configuration.store>
Configuration Store Format
The configuration store follows the .NET configuration XML format with a special configuration section holding all the configuration information. The section allows for configuration settings for multiple applications to be stored, as well as on the global level. There is also the concept of tokens (more on that later). Each configuration entry is defined as a property name (i.e. configuration key), the data type and the value. You can use data structures as property values as well.

Here is an example that tries to illustrate all these features:

<configuration>
 <configSections>
  <section name="ak.commons.configuration" type="AK.Commons.Configuration.Sections.ApplicationSettingsConfigurationSection, AK.Commons"/>
 </configSections>
 <ak.commons.configuration>
  <applicationSettings>
   <application>
    <settings>
	 <setting name="setting1" type="System.String" value="globalvalue" />
	 <setting name="tokenizedSetting" type="System.String" value="Abc{LocalPath}" />
    </settings>
    <tokens />
   </application>
   <application name="Application1">
	<settings>
	 <setting name="setting1" type="System.String" value="app1value" />
	 <setting name="setting2" type="System.String" value="Microsoft" />     
	 <setting name="setting3" type="System.Boolean" value="False" />
	 <setting name="setting4" type="MyType" value="">
	  <properties>
	   <property name="Prop1" value="20" />
	   <property name="Prop2" value="Sample" />
	   </properties>
	   <constructorParameters>
	   <param name="param1" Value="abc" />
	   </constructorParameters>
	  </setting>
	</settings>
    <tokens>
	 <token name="LocalPath" value="C:\Scratch" />
	</tokens>
   </application>
   <application name="Application2">
	  ...
   </application>
  </applicationSettings>
 </ak.commons.configuration>
</configuration>
The global node is the application node without a name. It is required, but can have an empty settings and tokens sub-nodes. When you initialize the application using an application name (see Initialization), the global configuration is combined with the application specific configuration for that application and loaded into memory. For entries with the same configuration keys, global ones are overridden by application specific ones. You can also define tokenized configuration values as shown above and then define different token replacement values for different applications. This comes in handy where a certain setting is pretty much the same across multiple applications, with only one identifier or something of the sort that is different.
Configuration Interface
Once you've "configured the configuration store" with the call to AppEnvironment.Initialize() (see Initialization), you can access the configuration interface using AppEnvironment.Config or with a MEF imported instance of AK.Commons.Configuration.IAppConfig (similar to how IComposer and IAppLogger work). The interface has dictionary-type Get and TryGet methods you can use to access the setting values.

Here are a few examples (assuming we have a IAppConfig instance).

var mySetting1 = config.Get<string>("MySetting1"); // throws if setting is not present.
var mySetting2 = config.Get<MyType>("MySetting2"); // throws if setting is not present
var mySetting3 = config.Get("MySetting3", "DefaultValue");
var success = config.TryGet("MySetting4", out mySetting4); // you get the idea.
Logging
You access the logging interface much like the composition or configuration interface, i.e. through AppEnvironment.Logger or a MEF imported instance of AK.Commons.Logging.IAppLogger.

All logging is asynchronous and can use multiple providers. Everytime you log something, it goes into a queue which is processed by another thread that removes items from the queue and sends it to all configured, enabled logging providers. The logging interface has methods corresponding to each verbosity level (i.e. Verbose, Information, Warning and Error - in decreasing order of verbosity). You can set the verbosity level using the configuration key ak.commons.logging.loglevel and setting the values to "Verbose", "Information" and so on.

Each provider may have its own settings that need to be specified.

Simple examples:

logger.Information("This thing happened.");
logger.Error(exception);
logger.Warning("Oops!");
There are two built-in providers: one that logs to the console and a very simple one that logs to text files.
Exceptions
The library provides a base class called AK.Commons.Exceptions.ReasonedException that has some formatting features for logging, and lets you specify error codes as an Enum - and also lets you override a method to provide friendly descriptions for each enumerated value.

Besides this, there are some convenience extension methods for System.Exception that let you wrap an exception as a given ReasonedException, log it using IAppLogger and/or re-throw it.

If you import the namespace AK.Commons.Exceptions, you should be able to use these methods: Wrap, WrapAndLog, WrapAndThrow, WrapLogAndThrow, etc.
Data Access
For data access, there are constructs to support the Unit-of-Work and Repository patterns. You get to the data access interface using AppEnvironment.DataAccess or a MEF imported instance of AK.Commons.DataAccess.IAppDataAccess. You can use it as a dictionary to look up a unit-of-work factory by name or get the default nameless one using the Default property. Once you have one, you can use the Create method on the factory to get an instance of IUnitOfWork - which is an IDisposable. You can therefore put your data access code inside a using block and let the library and the provider handle sessions, transactions, etc.

Once you have entities, you can build repositories by implementing IRepository or better yet extending RepositoryBase. Once inside a unit-of-work, you have to assign that unit to each repository you want to take part in the transaction using the UnitOfWork property on the repository. Here's an example (assuming we have an IAppDataAccess instance):

using (var unit = appDataAccess["myDb"].Create())	
{
	myRepo1.UnitOfWork = unit;
	myRepo2.UnitOfWork = unit;
	
	// Perform operations on myRepo1 and myRepo2.
	
	unit.Commit();
}
							
This can get a bit repetitive if you have multiple repositories - so there's an extension method that lets you write the above code as:

appDataAccess["myDb"]
	.With(myRepo1, myRepo2, myRepo3)
	.Execute(unit =>
	{
		// Do stuff.
	});
The IRepository interface has query and update type methods that lend themselves well to LINQ and IQueryable. The idea is to be able to abstract different types of data access providers well.

You configure data access providers as follows:

<setting name="ak.commons.dataaccess.uowfactory.factoryName.provider" type="System.String" value="providerName" />
<setting name="ak.commons.dataaccess.uowfactory.factoryName.provider_specific_setting1" ... />
<setting name="ak.commons.dataaccess.uowfactory.factoryName.provider_specific_setting2" ... />
<setting name="ak.commons.dataaccess.uowfactory.factoryName.provider_specific_setting3" ... />
Here's an example of a factory called "myDb" (as shown in the code examples above) that uses the Fluent NHibernate provider (part of the Commons Providers library).
<setting name="ak.commons.dataaccess.uowfactory.myDb.provider"
 type="System.String" value="FluentNHibernate" />
<setting name="ak.commons.dataaccess.uowfactory.myDb.connection.provider"
 type="System.String" value="NHibernate.Connection.DriverConnectionProvider" />
<setting name="ak.commons.dataaccess.uowfactory.myDb.connection.driver_class"
 type="System.String" value="NHibernate.Driver.SqlClientDriver" />
<setting name="ak.commons.dataaccess.uowfactory.myDb.connection.connection_string"
 type="System.String" value="Server=(local);Database=MyDb;Integrated Security=SSPI;" />
<setting name="ak.commons.dataaccess.uowfactory.myDb.dialect"
 type="System.String" value="NHibernate.Dialect.MsSql2005Dialect" />
You can build your own factory provider by implementing IUnitOfWorkFactory and using it to provide your own implementation of IUnitOfWork. You need to decorate the class with ProviderMetadataAttribute to give it a unique provider name (such as "FluentNHibernate" in the above example).

Each repository gets the following methods:
  • Get
  • GetAll
  • GetFor
  • GetList
  • Save
  • Delete
Ideally, one should be able to get by with just these methods used within units of work as required.

Web
Currently, there's only 2 web features (other than composition, see Composition/DI for that): an interface to support script and CSS bundling, and a light web authentication interface that can be used for SSO.

To access the bundle configurator, use AppEnvironment.BundleConfigurator or a MEF imported instance of AK.Commons.Web.Bundling.IBundleConfigurator. You can use it to configure bundling based on a JSON string. You can implement the IBundleConfigurator interface to build your own provider, and decorate it with ProviderMetadataAttribute to give it a unique provider name, much like you do with data access.

In your application, you decide which provider to use through the ak.commons.web.bundling.provider configuration key.

For SSO, there's the AK.Commons.Web.Security.IWebAuthenticator interface - pretty much the same pattern as bundle configurator - you pick which one to use through the ak.commons.web.security.webauth.provider configuration key, and so on.

There's also the WebAuthenticationFilterAttributeBase class (wow, that's a mouthful). You can extend this class to implement your own authentication filter - there's different overrides that represent different hookup points in the SSO authentication process.