Stack overflow in XBAP app using Ninject

131 views Asked by At

When I use Ninject with any extension in XBAP (WPF Browser) application, I get Stack Overflow exception (small pun intended).

Here's stack trace. It's rather large, but complete (that's why I've posted it on pastebin):

http://pastebin.com/su9M1c7V

I'm trying to use Conventions and Factory extensions for Ninject. If I reference assembly of either one, I get Stack overflow exception. So to be clear, when I remove references to both libraries, application runs correctly.

It's really weird, because Ninject seems to be creating new AppDomain, but CLR apparently tries to load entry/executing assembly (the only one in my solution) and execute it. That obviously leads to Stack overflow exception.

I'm also using Caliburn.Micro, plus additional libraries: Caliburn.Micro.Contrib, Caliburn.Micro.Extras (along with their dependencies) - all latest versions.

Does anyone have an idea, what's causing this and how to fix it?

1

There are 1 answers

0
mnn On BEST ANSWER

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).