After fiddling around with AppDomains, I've found out that Ninject has nothing to do with this.
(an extensive explanation follows, solution/workaround is at the end of the answer)
Ninject creates seperate AppDomain
in AssemblyNameRetriever
to retrieve assembly names. In my case, those assemblies are Ninject extensions:
private static AppDomain CreateTemporaryAppDomain()
{
return AppDomain.CreateDomain(
"NinjectModuleLoader",
AppDomain.CurrentDomain.Evidence,
AppDomain.CurrentDomain.SetupInformation);
}
The problem lies with the object AppDomainSetup
stored in AppDomain.CurrentDomain.SetupInformation
property. It has ActivationArguments
property set to instance of ActivationArguments
class, which contains information that causes entry assembly to execute (which is fine, since XBAP application has to start somehow).
However, since Ninject uses same setup information, this causes infinite recursion and thus our favorite StackOverflow exception.
The workaround is to set property ActivationArguments
to null
. However, AppDomain
class creates a copy of AppDomainSetup
object in SetupInformation
property getter. Thus it is necessary to get a copy of AppDomainSetup
object, set ActivationArguments
to null
and via reflection set value _FusionStore
field of AppDomain
class to this object.
TL;DR: Before creating Ninject kernel, we have to invoke this code:
var setupInformation = AppDomain.CurrentDomain.SetupInformation;
setupInformation.ActivationArguments = null;
var field = typeof(AppDomain).GetField("_FusionStore", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(AppDomain.CurrentDomain, setupInformation);
No idea if this will cause any issues later. Thus far, I believe this code requires full trust, because it accesses private field (and sets its value).