Geeks With Blogs
Freestyle Coding Programming in the Real World

Microsoft keeps telling us that we should create interfaces for everything and program to them. This is all fine and dandy, but this can become a nightmare when dealing with dynamically loaded libraries.

Let us begin with an interface:

namespace Interfaces {
public interface ICommon {
string RequiredField { get; }
void DoSomethingWithTheRequiredField();
}
}

Now, we will create 2 different implementations of the interface. The first will implement ICommon for use with our Sql database:

namespace Sql {
public class SqlCommon : ICommon {
public string RequiredField { get; private set; }
public void DoSomethingWithTheRequiredField() {
RequiredField += "Sql";
}
}
}

The first will implement ICommon for use with our Xml database:

namespace Xml {
public class XmlCommon : ICommon {
public string RequiredField { get; private set; }
public void DoSomethingWithTheRequiredField() {
RequiredField += "Xml";
}
}
}

Here in lies the challenge. Our application doesn't know which library is loaded. For that matter, we could create a third library that used a custom binary file. Thus, our application cannot have any knowledge of the contents of the library.

The solution is not quite as difficult as one may think. I used a factory pattern to wrap the assembly. This allowed me to pull the class on the fly. However, once the assembly was opened, I would have no way of knowing which namespace existed in the assembly. In order to get around this, I just used what I did know:

using Interfaces;
using System.Reflection;
using System.Configuration;
namespace Application {
internal static class DatabaseFactory {
private static string DataLibrary = ConfigurationManager.AppSettings["DataLibrary"];
private static Assembly assembly = null;
private static Assembly DataAssembly {
get {
if( assembly == null ) {
assembly = Assembly.Load( DataLibrary );
}
return assembly;
}
}
private static string GetFullName( string name ) {
foreach( Type res in DataAssembly.GetExportedTypes() ) {
foreach( Type iface in res.GetInterfaces() ) {
if( iface.Name == name ) {
return res.FullName;
}
}
}
throw new ArgumentException( "Unknown type requested from " + DataAssembly.GetName().Name );
}
private static object GetNewInstance( string name ) {
return DataAssembly.CreateInstance( GetFullName( name ) );
}
public static ICommon GetCommonDataProvider() {
return GetNewInstance( "ICommon" ) as ICommon;
}
}
}

The true magic is contained in GetFullName. I know the name of my interface. Thus I get a list of everything in the assembly and search for the one that uses my interface. Once I find the type, I can pull the FullName, which is the required parameter for CreateInstance.

Now, before you complain, and I can hear you, Yes. This is not the most efficient way of handling the problem. As it stands, I am reflectively parsing the assembly every time I need a new ICommon.

That, however, isn't the point of this post. We'll have to leave static caching for another day.

Posted on Wednesday, October 6, 2010 8:13 PM .NET , C# , Interfaces , Reflection | Back to top


Comments on this post: Dynamic Library Loading

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Chris Gardner | Powered by: GeeksWithBlogs.net