Bikeman868/UrlRewrite.Net

Bad assumption with the use of PackageLocator().ProbeBinFolderAssemblies() in UrlRewrite.Utilities.NinjectFactory!

Closed this issue · 3 comments

Cross posted as this may or may not be a root cause issue with Ioc.Modules project (see: Bikeman868/Ioc.Modules#1). After cloning down the source code I think that the real issue is the assumption here with UrlRewrite.Net.

We have an application for which I'm trying to use UrlRewrite.Net (an excellent solution by the way). However, our application requires the use of a Platform API that has dll dependencies that are not all managed code. To be specific it requires that a file called xmogrt.dll (from the JuggerNet Java proxy project) to be in our bin folder of the application!

This fails when the method ProbeBinFolderAssemblies() runs, as it's called in the UrlRewrite.Utilities.NinjectFactory class, with an exception saying "BadImageFormatException: Could not load file or assembly 'xmogrt' or one of its dependencies. The module was expected to contain an assembly manifest." This is because it's not a managed .Net dll assembly.

To fix this I have changed line 14 from:
var packageLocator = new PackageLocator().ProbeBinFolderAssemblies();

to use the less risky call:
var packageLocator = new PackageLocator().ProbeAllLoadedAssemblies();

All Unit tests pass and the Test website works. And this now allows UrlRewrite.Net to work in our project.

Would appreciate your thoughts on this change, Thanks!

The reason that I added a few different ways of adding assemblies to the PackageLocator was to provide flexibility for the numerous scenarios that I couldn't foresee. It looks like you have one of those scenarios, and probing loaded assemblies instead of all assemblies in the bin folder is a reasonable solution.

Please bear in mind that .Net loads assemblies as-needed, and at the point where you initialize the PackageLocator your application might not have loaded all of its assemblies yet. The ones that are not loaded yet could be missing from the IoC registrations. If you find yourself in this situation then the PackageLocator can be instructed to register specific assemblies, and if you do this then the packages that are explicitly loaded will take precedence over assemblies found by probing. This can also be useful when you have two packages that register concrete implementations of the same interface and you want to define the order in which they are registered.

You are right that the assumption made by the NinjectFactory is naive, and not appropriate for your situation. I mostly included this factory in UrlRewrite to make getting started with UrlRewrite very straightforward, but I also made provision for you to supply your own factory implementation if the default one didn't work for you.

It looks like you managed to find the solution already. Using a customized version of the NinjectFactory is the correct way to solve the problem, just be aware of the issues around ProbeAllLoadedAssemblies() and on-demand loading of assemblies.

Martin, thanks for the response. Yeah, I just realized tonight that the RewriteModule.Initialzie()overload does support passing in a custom IFactory implementation of my own -- Doh! That would have solved it perfectly, without downloading the source to change that line. During my late night I was thinking that was a static method being called . . .

Very nicely done, just wish I had noticed it sooner. I'll delete the source, and implement my own IFactory (based off the NinjectFactory) and then just pass it in to resolve my issues.

Yep, that all makes sense. I def. understand the issues with .Net loading assemblies on demand, and this works fine for me since I'm not using the Ioc.Modules specifically for anything othter than the fact that it is a dependency of UrlRewrite.Net. And, since it doesn't break UrlRewrite.Net then that will work perfectly. And you've confirmed that I guessed correctly in that the PackageLocator().ProbeAllLoadedAssemblies() works fine because the UrlRewrite assembly must already be loaded at the point that I make the first call to RewriteModule.Initialzie().

Thanks again for the quick responses!

You are welcome. Thank you for choosing UrlRewite.Net.