The Darkside

Shedding light on things and stuff

 
  Home :: Contact :: Syndication  :: Login
  83 Posts :: 0 Stories :: 56 Comments :: 2 Trackbacks

Ads

 

Donate via PayPal...

...if you feel the site helped.

Archives

Post Categories

Open Source Projects

Other Blogs

Following on from my previous post here on different methods of configuring ActiveRecord, I’ve decided to go into more detail on this  and more specifically into automatically loading assemblies and configuring ActiveRecord without much fuss.

Download

ARConfig.zip

Code

One of the many overloaded options for configuring ActiveRecord is by passing an assembly, or an array of assemblies, each assembly having ActiveRecord classes in them, which are in turn initialised by the ActiveRecordStarter.

A simple demonstration of this, also making use of the in-place configuration is:

ActiveRecordStarter.Initialize(Assembly.GetExecutingAssembly(), ActiveRecordSectionHandler.Instance);

This will make ActiveRecord load the currently executing assembly and try to register all the ActiveRecord classes that it finds.

Building on this, we can have a look at a mechanism that loads all assemblies in the folder that your currently executing application is running. Although there is a certain amount of overhead doing all this processing, it does have the positive side of not having to worry about constantly revisiting your ActiveRecord initialisation code. This is especially true if you've got classes in different assemblies.

To begin with, we need to find all the assemblies in the current folder (presumably all these are all part of your running application), that have a reference to ActiveRecord. 

private static Assembly[] GetAssembliesToInitialise()
{
 
    var assembliesToInitialise = new Dictionary<string, Assembly>();
    foreach (string dllPath in GetAssemblyPaths())
    {
        Assembly assembly;
        try
        {
            assembly = Assembly.LoadFile(dllPath);
        }
        catch   //Win32/COM+ DLL's need to be skipped, so catch the exception and continue
        {
            continue;
        }
        if (IsAssemblyDependentOnActiveRecord(assembly))
        {
            string fileName = Path.GetFileName(dllPath);
            if (!assembliesToInitialise.ContainsKey(fileName))
                assembliesToInitialise.Add(fileName, assembly);
        }
 
    }
    return assembliesToInitialise.Values.ToArray();
}
 
private static string[] GetAssemblyPaths()
{
    var u = new Uri(Assembly.GetExecutingAssembly().CodeBase);
    string directory = Directory.GetCurrentDirectory(); //Use this as the default...
    if (u.IsAbsoluteUri)
        directory = Path.GetDirectoryName( u.AbsolutePath);
    return Directory.GetFiles(directory, "*.DLL", SearchOption.AllDirectories);
}

The code above only searches for files with the .DLL extension - you may want to alter it to search for EXEs as well, or just to search the current directory.

Next we need to determine if the file is an actual assembly and not a Win32/COM+ library. The assembly gets loaded first in the code above (which determines if it's an assembly) and then it is processed to determine if it is dependent on Castle ActiveRecord.

private static bool IsAssemblyDependentOnActiveRecord (Assembly assembly)
{
    //Just a small optimisation to skip system files that may be set to copy local 
    if (assembly.GetName().ToString().ToUpper().StartsWith("SYSTEM."))
        return (false);
    //Now do the work for other files
    AssemblyName[] dependancies = assembly.GetReferencedAssemblies();
    foreach (var dependancy in dependancies)
    {
        if (dependancy.ToString().ToUpper().StartsWith("CASTLE.ACTIVERECORD"))
            return (true);
    }
    return (false);
}

 This isn't a sure-fire way of checking that your assembly actually has ActiveRecord class, but it is a good starting point and minimizes some of the work that the ActiveRecordStarter needs to do.

If the assembly passes all these tests, it is added to an array of assemblies, which is the passed to the ActiveRecordStarter.Initialize method which accepts an array of assemblies. The final routine for putting this all together looks as follows:

public static void Initiliase ()
{
    //Don't intialise this again if already is initialised
    if (ActiveRecordStarter.IsInitialized)  
        return; 
 
    //Get the assemblies that need to be initialised
    Assembly[] assembliesToInitilise = GetAssembliesToInitialise();
    if (assembliesToInitilise.Length == 0)
        return;
 
    //Use the ActiveRecordStarter to initialise the assemblies
    ActiveRecordStarter.Initialize(assembliesToInitilise, ActiveRecordSectionHandler.Instance);
}

You can simply call it like this to test it, and in your application, it's a one-liner:

static void Main()
{
    ActiveRecordInitialiser.Initiliase();
    Console.WriteLine("Is ActiveRecord initialised :" + ActiveRecordStarter.IsInitialized.ToString());
}

If you want to make use of the HttpModule, you need it to your web config file as follows:

<httpModules>
  <add name="Darkside.ActiveRecordInitialiser" type="Darkside.ActiveRecord.Configurator.ActiveRecordInitialiserHttpModule, Darkside.ActiveRecord.Configurator"/>
</httpModules>

The module

posted on Tuesday, June 24, 2008 2:45 PM

Feedback

# New and Notable 274 10/25/2008 6:28 PM Sam Gentile If (DeveloperTask==Communication &amp;&amp;
Haven&#39;t wrote much because I am saving up for a big post on Castle Active Record, which I am just

# New and Notable 274 12/2/2008 3:14 AM Sam Gentile's Blog
<p>Haven't wrote much because I am saving up for a big post on Castle Active Record, which I am just really, really enjoying right now in my work. I know we made a good choice. More on that soon. NHibernate/Castle Chad Meyers has posted source/binaries for his recent NHibernate Intro screencasts that are...</p>

Comments have been closed on this topic.