0

I am trying to implement a plugin architecture for our WPF program following the proposed implementation here. I want my plugins to reside in a separate folder from the main program folder. I have gotten it to only partially work. Here is the code:

The plan is for each plugin to provide its own StructureMap registry to override the default StructureMap regstry.

The plugin I am currently working on has the following registry and as you can see, I am overriding the registry for the plugin-type IPrintProgramExecutor to intercept and use AutomationController instead. And it works as expected:

public class PluginRegistry : Registry
{
    public PluginRegistry()
    {
        this.ForConcreteType<AutomationController>()
            .Configure
            .Ctor<IPrintProgramExecutor>().Is(c=> c.GetInstance<PrintProgramExecutor>())
            .Singleton();
        this.For<IAutomationController>().Use(c => c.GetInstance<AutomationController>()).Singleton();
        this.For<IPrintProgramExecutor>().Use(c => c.GetInstance<IAutomationController>()).Singleton();
        //this.ForConcreteType<AutomationPlugin>()
        //    .Configure
        //    .Singleton();
        this.For<IPluginBase>().Use<AutomationPlugin>();
    }
}

AutomationPlugin currently is this stub:

public class AutomationPlugin : IPluginBase
{
    public ViewModelBase ViewModel {
        get { return viewModel; }
        private set { viewModel = value; }
    }
    public ResourceDictionary View { get; }

    private ViewModelBase viewModel { get; set; }
    private ResourceDictionary viewDictionary = new ResourceDictionary();

    public AutomationPlugin()
    {
         // do something meaningfull!
    }
}

with IPluginBase:

public interface IPluginBase
{
    ViewModelBase ViewModel { get; }
    ResourceDictionary View { get; }
}

The class to add the registry is this, where pluginPath is the path to the extension folder:

public class PluginRegistryAdder : Registry
{
    public PluginRegistryAdder(string pluginPath)
    {
        Scan( x =>
        {
            x.AssembliesFromPath(pluginPath);
            x.LookForRegistries();
        });
    }
}

The class to actually tie in the plugin registry using the code above is this:

public static class ExtensionManager
{
    public static void RegisterPluginsInDic(string pluginPath, IContainer container)
    {
        var pluginRegistries = new PluginRegistryAdder(pluginPath);
        container.Configure(_ => _.IncludeRegistry(pluginRegistries));
        var whatIHave = container.WhatDoIHave(typeof(IPluginBase));
        var plugins = container.Model.GetAllPossible<IPluginBase>(); // the IEnumerable plugins is empty although I am registering `AutomationPlugin` for it. Why?!
    }
}

Now, as mentioned above, the interception for the plugin-type IPrintProgramExecutor works as expected. But for some reason container.Model.GetAllPossible<IPluginBase>() and container.WhatDoIHave(typeof(IPluginBase)) do not find any registered types for the plugin-type IPluginBase. I have tried calling these methods for IPrintProgramExecutor and surely enough they return the concrete type. I have been looking quite a while for the reason and cannot find it.

Any ideas why? Could it have to do with the fact, that I am calling container.Configure(...) twice and perhaps the fact that I already register something for IPringProgramExecutor the first time I call container.Configure(...)? Help is greatly appreciated!

Updates:

  1. After switching to my laptop, the interception, that previously worked, does not work anymore. Furthermore, I am now getting an exception, that one of the assemblies I am trying to register in PluginRegistry is not found:

StructureMap.StructureMapException: Unable to create an instance for Registry type 'Extensions.Automation.PluginRegistry'. Please check the inner exception for details ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Automation.Servers.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. at Extensions.Automation.PluginRegistry..ctor() ...

All in all, it seems like a path-problem that I cannot figure out. I suspect, that at run-time the program attempts to load the DLLs in the Plugin-registry from the main path, but the corresponding DLLs/asseblies reside in the Extension-folder. How can I see from where StructureMap attempts to load the assembly Automation.Servers.Interfaces for debugging? Hope somebody can help me out. I am slowly loosing it.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
packoman
  • 1,230
  • 1
  • 16
  • 36

1 Answers1

0

You should be able to see where StructureMap is trying to probe for assemblies with the type scanning diagnostics: http://structuremap.github.io/diagnostics/type-scanning/

You do have the ability to specify the folder instead of relying on the AppDomain/AppContext.