I found the cause of my problem and also found a (not so nice) workaround. Maybe you guys know a better way of fixing this?
This is how it looks:
namespace Diamir.Epi.Migrations.Initialization
{
[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class MigrationInitialization : IConfigurableModule
{
/// <summary>
/// Adds all types that implements interface IMigration to the IOC container
/// </summary>
/// <param name="context"></param>
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.StructureMap().Configure(c =>
{
c.AddRegistry((MigrationRegistry)Activator.CreateInstance(typeof(MigrationRegistry)));
});
}
public void Initialize(InitializationEngine context) { }
public void Uninitialize(InitializationEngine context) { }
}
}
namespace Diamir.Epi.Migrations
{
public class MigrationRegistry : Registry
{
public MigrationRegistry()
{
Scan(s =>
{
s.TheCallingAssembly(); // tested also s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IMigration>();
s.SingleImplementationsOfInterface().OnAddedPluginTypes(t => t.Singleton());
});
}
}
}
I'm not sure why moving the initialization code to another assembly solves the problem and I know this fix is rather bad for a number of different reason. Can't even be sure that the InitializationCode.cs can compile in the consumers project. Anyone have any other suggesttions?
How do you usually handle Initialization code in plugins, where the idea is that the consumer project should be able to add classes that implements an interface provided by your plugin and these classes should be put in the IOC sandbox?
I found a better workaround!
Basic problem was that when I used s.AssembliesFromApplicationBaseDirectory(); in StructureMap Scan it scanned all assemblies (including all EPiServer-assemblies) and tried to find implementations of my IMigration interface and add them to the IOC. This for some reason generated the error above.
If I excluded all EPiServer assemblies in the Scan by use this code when scanning the assemblies, it works fine. I can now keep the init module and IOC registration in my nuget plugin.
public class MigrationRegistry : Registry
{
public MigrationRegistry()
{
// Need to exclude EPiServer assemblies since we get non-thread-safe-exceptions if we include them in scan.
var nonEpiAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(x => !x.FullName.ToLowerInvariant().Contains("episerver"));
foreach (var assembly in nonEpiAssemblies)
{
Scan(s =>
{
s.Assembly(assembly);
s.AddAllTypesOf<IMigration>();
s.SingleImplementationsOfInterface().OnAddedPluginTypes(t => t.Singleton());
});
}
}
}
Maybe there is a better solution, but this is far better than the previous workaround.
for my libraries I actually tend to provide lambda for the hosting environment to provide filter expression for me to execute before concluding on scanable list of assemblies. sometimes it's not worth to wait for the scanner to do job on Microsoft.* or System.* assemblies if I know that it's not worth that and library will not find anything interesting there..
I get the above error the _second_ time I run
If I IIS-reset it works _one_ time, then I get the above error again. Same thing applies to
Any ideas what I'm doing wrong?