August 10, 2008

Loading Objects Using Reflection

This helper class loads a bunch of objects from assemblies found in the specified search path. The objects must support an interface of the given type eg usage. List<ISomeInterface> plugIns = PluginHelper.LoadPlugins <ISomeInterface>(@".\");
class PluginHelper
{

  // Loading a bunch of objects dynamically using reflection
  // In this case the type parameter specifies an interface for
  // an object with a public default constructor
  public static IList<INTERFACE> LoadPlugins<INTERFACE>(
         string searchPath)
  //where INTERFACE :  // (only reference types)
  {
    List<INTERFACE> objList = new List<INTERFACE>();

    string[] files = Directory.GetFiles(searchPath, "*.dll");
    foreach (string file in files)
    {
      try
      {
        Assembly assembly = Assembly.LoadFrom(file);
        foreach (Type type in assembly.GetTypes())
        {
          if (!type.IsClass || type.IsNotPublic) continue;
          Type[] interfaces = type.GetInterfaces();
          if (((IList<Type>)interfaces).Contains(typeof(INTERFACE)))
          {
            try
            {

              // Find the default constructor
              ConstructorInfo conInfo = type.GetConstructor(new Type[0]);
              bool hasPublicDefaultConstructor = ((conInfo != null) &&
                  ((conInfo.Attributes | MethodAttributes.Public) > 0));
              if (hasPublicDefaultConstructor)
              {
                object obj = Activator.CreateInstance(type);
                INTERFACE instance = (INTERFACE)obj;
                Debug.Assert(instance != null);
                objList.Add(instance);
              }
              else
              {
                Trace.WriteLine("LoadPlugins<INTERFACE>() - Can not create the type \'" +
                    type.ToString() + "\' in assembly \'" + file +
                    "\' as it does not have a public default constructor");
              }
            }
            catch (Exception ex)
            {
              Trace.WriteLine("Exception occurred creating an instance of \'" +
                  type.ToString() + "\' from assembly \'" + file + "\'");
            }

          }

        }
      }
      catch (Exception ex)
      {
        Trace.WriteLine("Exception occurred trying to load from assembly \'" +
            file + "\'");
      }
    }
    return objList;
  }

}

No comments: