Adding dynamic redirects. Fix for #793

Fix for #793 

*Do not merge this yet!!!!*

This change removes all static binding redirects in app.config, and introduces dynamic redirects in core. The way this is done is by listening to the AssemblyResolve event on the AppDomain, and loading / returning the assembly to redirect to. It turns out using this technique you can swap on the fly and give a different assembly than what was requested.

At startup, it builds a map in map in memory based on the assemblies that scriptcs ships with ensuring that any requests for the same names will be redirected to it's version. It also ensures that any packages in the scriptcs packages folder take precedence over what the script pack / packages assemblies were actually compiled against.

Assembly black magic at its finest....

It appears to work so far :-)

This does not fix the Service Stack script pack issue, as there appears to be no magical fix for that other than updating the script pack. However, I was able to get the old Web Api script pack to work with the latest Web Api (see comments)


Yeah, perhaps a regular static method is best for now. Not the nicest, but
we can always look at refactoring this out later somehow.

If it were an extension method on `IEnumerable<string>` then I think it
would have to be `internal` to avoid extension method pollution.


On Thu, Jul 24, 2014 at 10:42 AM, Glenn Block <notifications@github.com>
wrote:

> In src/ScriptCs.Hosting/ModuleLoader.cs:
>
> > @@ -85,7 +87,7 @@ public void Load(IModuleConfiguration config, string[] modulePackagesPaths, stri
> >              var paths = new List<string>();
> >              foreach (var modulePackagesPath in modulePackagesPaths)
> >              {
> > -                var modulePaths = _resolver.GetAssemblyPaths(modulePackagesPath);
> > +                var modulePaths = _resolver.GetAssemblyPaths(modulePackagesPath).Where(m=>m.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase));
>
> IEnumerable<string> could also just do a straight static method.
> … <#147678999530714f_>
> On Thursday, July 24, 2014, Adam Ralph <notifications@github.com> wrote:
> In src/ScriptCs.Hosting/ModuleLoader.cs: > @@ -85,7 +87,7 @@ public void
> Load(IModuleConfiguration config, string[] modulePackagesPaths, stri > var
> paths = new List<string>(); > foreach (var modulePackagesPath in
> modulePackagesPaths) > { > - var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath); > + var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath).Where(m=>m.EndsWith(".dll",
> StringComparison.InvariantCultureIgnoreCase)); Yeah, I guess that would
> work. On what type would the extension method be? … <#14767813f010d274_> On
> Thu, Jul 24, 2014 at 10:21 AM, Glenn Block <notifications@github.com
> <javascript:_e(%7B%7D,'cvml','notifications@github.com');>> wrote: > In
> src/ScriptCs.Hosting/ModuleLoader.cs: > > > @@ -85,7 +87,7 @@ public void
> Load(IModuleConfiguration config, string[] modulePackagesPaths, stri > >
> var paths = new List<string>(); > > foreach (var modulePackagesPath in
> modulePackagesPaths) > > { > > - var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath); > > + var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath).Where(m=>m.EndsWith(".dll",
> StringComparison.InvariantCultureIgnoreCase)); > > Rethinking this, I guess
> what we could do is encapsulate that simple > filter of dll and exe into an
> extension method which the two places that > need it can use. This way we
> at least centralize the logic? > … <#147677634f9ae75e_> > On Wednesday,
> July 23, 2014, Adam Ralph <notifications@github.com
> <javascript:_e(%7B%7D,'cvml','notifications@github.com');>> wrote: In
> src/ScriptCs.Hosting/ModuleLoader.cs: > @@ -85,7 +87,7 @@ public void
> Load(IModuleConfiguration config, string[] modulePackagesPaths, stri > var
> paths = new List<string>(); > foreach (var modulePackagesPath in
> modulePackagesPaths) > { > - var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath); > + var modulePaths =
> _resolver.GetAssemblyPaths(modulePackagesPath).Where(m=>m.EndsWith(".dll",
> StringComparison.InvariantCultureIgnoreCase)); Having said that, I can see
> that there is already some generalised logic in
> AssemblyResolver.GetBinAssemblyPaths() which restricts to .dll and .exe and
> checks for a managed assembly
> https://github.com/scriptcs/scriptcs/blob/dev/src/ScriptCs.Core/AssemblyResolver.cs#L66-L69.
> AssemblyResolver.GetAssemblyPaths() unions the results of a call to
> GetBinAssemblyPaths() and a call to
> PackageAssemblyResolver.GetAssemblyNames() but the latter has it's own
> logic which does not perform the same restriction. I wonder if it's
> possible to reuse that same bit of logic everywhere so that it only needs
> to be done once? — Reply to this email directly or view it on GitHub <
> https://github.com/scriptcs/scriptcs/pull/798/files#r15330937>. — Reply
> to this email directly or view it on GitHub <
> https://github.com/scriptcs/scriptcs/pull/798/files#r15334895>. — Reply
> to this email directly or view it on GitHub <
> https://github.com/scriptcs/scriptcs/pull/798/files#r15335353>.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/scriptcs/scriptcs/pull/798/files#r15335665>.
>