[IronPython] Feature request: Make assembly loadingstrategy configurable.

Jeff Brown Jeff at ingenio.com
Tue Feb 20 22:03:35 CET 2007


Yes, it would be much better if I could disable the built-in
AssemblyResolve hook.  From my perspective it would be better if the
script could do it dynamically at runtime.  Say,

clr.EnableAssemblyResolveHook = False
or
clr.AssemblyResolveMode = AssemblyResolveMode.LoadFromPath / Custom /
etc... if there were several

It's unfortunate that the CLR assembly loading model doesn't allow
extending the assembly resolution path beyond the app-base folder.  Oh
well.  I won't hold my breath.

So it's clear that Iron Python requires an AssemblyResolve hook to
present the illusion of a coherent sys.path.  But LoadFile is bad news.
It breaks compositionality of Iron Python with respect to assembly
resolution.  OTOH, LoadFrom with an Assembly Resolve hook will satisfy
case #1 and #2 below.  I'm just not convinced of the merit of case #3.

With case #3 there are a couple of problems.  The issue of reloading
assemblies is very challenging given that assemblies cannot truly be
unloaded.  The issue of loading an assembly and its dependencies from a
_specific_ non-standard location is also difficult and should really be
dealt with directly by adding references to specific files rather than
by means of Assembly Resolve (because we might load those dependencies
from the wrong places if we're given a choice on the path).  Most of the
time LoadFile just creates problems because the user isn't interested in
loading the Assembly from that _specific_ location but rather just
happens to know that a satisfactory copy exists there.

I believe the cases where LoadFile must be used are quite limited.  They
require careful attention to details when loading dependencies and when
resolving names.  The average user is just not likely to encounter this
situation.  Indeed many programs make assumptions about the uniqueness
of type names that would fail otherwise.

So I argue that the AssemblyResolve hook be changed to use LoadFrom but
that the AddReferenceToFile and AddReferenceToFileAndPath methods remain
as they are with LoadFile.  The latter should be considered advanced
usage.  The preferred option would be for the user to extend sys.path
and then use AddReference.  We could draw attention to this process by
introducing an AddReferencePath method that internally would just extend
sys.path (or perhaps some private assembly reference path *shrug*).
Alternately, the AddReference* methods could be changed to accept an
optional "pathHint" argument to be included in the sys.path. (yuck)

As for legitimate Assembly re-loading cases, perhaps there some other
API support that could help.  I don't know.

Thanks for your consideration,
Jeff.

-----Original Message-----
From: users-bounces at lists.ironpython.com
[mailto:users-bounces at lists.ironpython.com] On Behalf Of Dino Viehland
Sent: Monday, February 19, 2007 3:52 PM
To: Discussion of IronPython
Subject: Re: [IronPython] Feature request: Make assembly loadingstrategy
configurable.

Thanks for the suggestion.  I've opened a bug to track this but I don't
expect any immediate resolution here (the bug is
http://www.codeplex.com/IronPython/WorkItem/View.aspx?WorkItemId=8362).

The problem here is that we're trying to get several different scenarios
working correctly with our current assembly resolve logic:
        1. Assemblies with references to other assemblies
        2. Assemblies that exist outside of the AppDomain base path
        3. Re-loading of non-strongly signed assemblies

#1 requires either LoadFrom or LoadFile + Assembly Resolve Hooking so
that we can get all the assemblies loaded
#2 LoadFrom will work fine for the initial assembly but I believe it
breaks on any dependencies
#3 Requires LoadFile.

We might be able to add a command line switch that causes the resolve
event to be disabled for the process.  The unfortunate effect of that is
it's a big switch and might break code that expects to be able to load
assemblies using our already established mechanism.  If you own the
process though and everything that gets loaded into it this might work.
I realize you already have a workaround but would this one be better for
you?

Longer term we might be able to smarten this up (although it's really
already too smart :) ) and provide a LoadFrom API that disables this
(I'm thinking having a thread-static which our assembly resolve checks
and skips providing resolution if you called our LoadFrom API).

For the even longer term I believe we have told the CLR team about the
issues we've encountered and we're hoping they deliver something that
works better in the future :).  That's really far off though...

-----Original Message-----
From: users-bounces at lists.ironpython.com
[mailto:users-bounces at lists.ironpython.com] On Behalf Of Jeff Brown
Sent: Monday, February 19, 2007 1:00 AM
To: users at lists.ironpython.com
Subject: [IronPython] Feature request: Make assembly loading strategy
configurable.

Iron Python installs a rather dragonic AssemblyResolve hook.  It uses
Assembly.LoadFile to try to load an Assembly from the path when
resolution fails.  I would prefer if Assembly.LoadFrom were provided at
least as an option, if not just made the standard behavior (once again).

The problem in my case is that Iron Python is linking to an application
that installs its own AssemblyResolve hook based on LoadFrom.  Because
LoadFrom and LoadFile Assemblies are tracked separately it happens that
two copies of the same Assembly are loaded but they have incompatible
types so the application blows up.  What's more, there may actually be
several identical copies of the same assembly floating around the search
path.  This is because the application consists of an assortment of
plugin folders with locally copied (rather than shared) binaries.

Here's my current workaround.  Ugly huh?


import System;
System.AppDomain.CurrentDomain.remove_AssemblyResolve(System.Delegate.Cr
eateDelegate(System.ResolveEventHandler, clr,
"CurrentDomain_AssemblyResolve"))
def AssemblyResolveWithLoadFrom(sender, e):
    try:
        return System.Reflection.Assembly.LoadFrom(e.Name + ".dll")
    except:
        return None
System.AppDomain.CurrentDomain.add_AssemblyResolve(AssemblyResolveWithLo
adFrom)

Jeff.
_______________________________________________
users mailing list
users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
_______________________________________________
users mailing list
users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com



More information about the Ironpython-users mailing list