A little background first - I'm working on a server application that requires the ability to use multiple data access class libraries based on the resources available on the server it is installed on (MySQL, SQL Server, XML, etc.). The are currently implemented as modular plugins, where the executable is paired with the appropriate class library on the server and interacts with it through a defined interface (IDataAccess).
The following code is the constructor for a singleton class on the server that exposes the backend:
private IDataAccess mDB;
private MudData()
{
List<String> files = new List<String>(Directory.GetFiles(".", "*.dll"));
List<Type> accessors = new List<Type>();
foreach (String file in files)
{
try
{
Assembly test = Assembly.UnsafeLoadFrom(file);
System.Type[] types = test.GetTypes();
//See if any of the located types implement IDataAccess.
foreach (System.Type candidate in types)
{
if (candidate.GetInterface("IDataAccess") != null)
{
accessors.Add(candidate);
}
}
}
catch
{
//Eat this on purpose - still need to check the rest of the matches.
}
}
if (accessors.Count == 0)
{
throw new ApplicationException("No supported data access .dll was found.");
}
//TODO: Select from multiples if found, but for now just take the first match.
PropertyInfo target = accessors.First().GetProperty("Instance");
MethodInfo getter = target.GetGetMethod();
//Create a delegate for the reflected assembly so any exceptions propagate correctly.
Func<IDataAccess> dataDelegate = (Func<IDataAccess>)Delegate.CreateDelegate(typeof(Func<IDataAccess>), null, getter);
Object found = dataDelegate();
if (found != null)
{
mDB = (IDataAccess)found;
}
else
{
throw new ApplicationException("Attempt to load an instance of IDataAccess failed.");
}
}
Any exceptions at this point will be fatal, and are trapped and logged in the calling code before a (hopefully) graceful exit. This code is only called once at startup and the object it obtains isn't released until the application exits. I've been having a hard time finding information about the performance implications of using an object reference obtained this way, so I'd especially welcome comments from that direction. My assumption is that the main performance penalty is in obtaining the reference, but I haven't been able to find out whether or not that is true in practice.
I'm mainly looking for feedback on my method of connecting with the back-end, but am certainly open to comments/criticism of code style, practices, etc.
Thoughts?