ninject / Ninject

the ninja of .net dependency injectors
http://ninject.org/
Other
2.68k stars 528 forks source link

SerializationException when scanning for modules #246

Open timbussmann opened 7 years ago

timbussmann commented 7 years ago

Ninject's approach to scan assemblies for modules implemented by CreateTemporaryAppDomain can cause applications to receive a SerializationException when newing up a new StandardKernel. This behavior is caused to a known bug in the .NET Framework described here: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/mitigation-deserialization-of-objects-across-app-domains and is triggered by the attempt to read the current app domains evidence using AppDomain.CurrentDomain.Evidence.

To repro the issue, the app domain newing up a new StandardKernel with LoadExtensions enabled needs to set a non-serializable value in the logical callcontext CallContext.LogicalSetData("someKey", new NonSerializableClass());.

Here's the main part from the repro sample available here: https://github.com/timbussmann/NinjectRepro

[TestFixture]
public class WhenLoadingModules
{
    [Test]
    public void ShouldNotThrow()
    {
        CallContext.LogicalSetData("someKey", new NonSerializableClass());

        INinjectSettings settings = new NinjectSettings()
        {
            LoadExtensions = true,
            ExtensionSearchPatterns = new[] { "*.dll" }
        };
        var kernel = new StandardKernel(settings);

        Assert.Pass();
    }
}

Sadly, the workaround described in the issue won't work, as the call to get_Evidence is not triggered by user code.

scott-xu commented 7 years ago

Thanks for the info. Does Ninject add non-serializable object in logical call context?

timbussmann commented 7 years ago

@scott-xu not that I'm aware of (and the search also didn't yield any results)

but it's a quite common approach when running on .net framework < 4.6 to polyfill AsyncLocal