views:

230

answers:

3

So here's the deal. I've got my solution which has a few projects in it:

  • A wrapper project - this is just a console app that's currently standing in for a windows service during debugging.
  • A worker project - this contains the guts of the code. This way I can easily debug the code for the windows service without the headache.
  • A plugin library project - This contains a plugin factory to new up a concrete instance of a plugin.
  • A plugin project - This contains a concrete implementation of my plugin.

My wrapper application contains my app.config which my plugin should reference directly for self configuration. This way my wrapper application doesn't need to know anything other than it needs to call the adapter factory to new up the instance of the plugin.

<configuration>
  <appSettings>
    <add key="Plugin" value="Prototypes.BensPlugin" />
    <add key="Prototypes.BensPlugin.ServiceAddress" value="http://localhost/WebServices/Plugin.asmx" />
    <add key="Prototypes.BensPlugin.Username" value="TestUserName" />
    <add key="Prototypes.BensPlugin.Password" value="TestPassword" />
  </appSettings>
</configuration>

Wrapper project:

using Worker;

public class Program
{
    public static void Main()
    {
        var serviceProc = new ServiceProcess();
        serviceProc.DoYourStuff();
    }
}

Worker project:

using PluginLibrary;

namespace Worker
{
    public class ServiceProcess
    {
        public string GetRequiredAppSetting(string settingName)
        {
            /* Code to get a required configuration setting */
        }

        public void DoYourStuff()
        {
            string pluginTypeName = GetRequiredAppSetting("Plugin"); 
            //At this point, pluginTypeName = "Prototypes.BensPlugin"
            Type type = Type.GetType(pluginTypeName); //type == null, wth!?

            //string testTypeName = new BensPlugin().GetType().ToString();
            ///At this point, testTypeName = "Prototypes.BensPlugin"
            //Type testType = Type.GetType(testTypeName)
            ///And testType still equals null!

            if (type != null)
            {
                IPlugin plugin = PluginFactory.CreatePlugin(type);
                if (plugin != null)
                plugin.DoWork();
            }
        }
    }
}

Plugin library:

namespace PluginLibrary
{
    public interface IPlugin
    {
        void DoWork();
    }

    public class PluginFactory
    {
        public IPlugin CreatePlugin(Type pluginType)
        {
            return (IPlugin)Activator.CreateInstance(pluginType);
        }
    }
}

Plugin:

using PluginLibrary;

namespace Prototypes
{
    public class BensPlugin : IPlugin
    {
        public string ServiceAddress { get; protected set; }
        public string username { get; protected set; }
        public string password { get; protected set; }

        public void DoWork()
        {
            Trace.WriteLine("Ben's plugin is working.");
        }

        public BensPlugin()
        {
            /* Code to self configure from app.config */
        }
    }
}

Okay, so that sets the stage. Where I'm coming unstuck is in my worker project when I reference Type.GetType(pluginTypeName). My pluginTypeName is being pulled from the configuration correctly, but Type.GetType(pluginTypeName) returns null. I've tried newing up an instance of my plugin directly at that same place in the code:

var obj = new BensPlugin();

This works just fine, and obj.GetType().ToString() returns the exact same string as I have configured in the app.config.

Can anyone tell me why I can new up a concrete object at that point in the code, but Type.GetType(pluginTypeName) would fail?

+6  A: 

It could be that you need to specify which assembly the type is located in:

<add key="Plugin" value="Prototypes.BensPlugin, TheAssemblyName" />
Fredrik Mörk
If that's all it is, I'm going to be cursing very loudly :D Please hold...
BenAlabaster
Son of a $!%@$@# thank you very much :) That was it!
BenAlabaster
You're welcome. I'm glad I'm not in Canada, I guess ;)
Fredrik Mörk
+1  A: 

Is pluginTypeName using assembly-qualified naming? Is the Assembly that contains pluginTypeName showing as being loaded?

If you're using the Assembly-qualified name then .NET should be able to automatically load the assembly for you; if you aren't then I would guess that Type.GetType() is returning null since it can't locate an assembly containing the requested type.

STW
+1  A: 

Instead of calling Type.GetType(pluginTypeName), try Type.GetType(pluginTypeName, true). The boolean parameter indicates if the call should throw an exception in the event of a failure, instead of returning null - this way, you should get a (hopefully) better description of why GetType is failing instead of just a mysterious null!

Richard Downer