Jeroen Mostert
7/1/2008 9:37:00 PM
Luciano wrote:
> I'm facing a problem that could be completely resolved using .policy
> files, but I could not use GAC in my application.
>
I've had similar problems and policies quite simply don't work for
out-of-GAC assemblies -- I've tried. Though I'm open to some guru proving me
wrong, of course.
> Basically the app should follow the "Smart Client" guidelines. All the
> application plug-ins (implemented as .NET assemblies) should be placed
> in a common folder shared among different workstations using remote
> folders. So I cannot use the GAC facilities.
>
> Until the plug-ins are implemented as single assembly, all is working
> fine. I'm parsing the remote "plugin" folder and load all assemblies
> using Assembly.LoadFrom method. I'm using a single AppDomain.
>
> The problem is coming up now that we need to write several multi-
> assembly plugins. We basically need to write one or more common core
> assemblies (as "infrastructure" for these plugins) that will be
> referred by each plugin.
> The core assemblies should be versioned and shipped bundled in each
> plugin package.
>
> I need to declare backward compatiblity in the core assemblies to:
> a) avoid to have multiple version of core assemblies loaded in memory;
> b) to efficiently implement an inter-plugin communication layer.
>
> To have this working I need to declare a binding redirect (as in the
> app.config file). But I cannot change that .config file because
> several application version could be installed on each workstation.
> I basically need to use Publisher Configuration File, so each core
> assembly could declare redirection from the older compatible versions.
>
> A possible (but unwanted) solution for that is that the applciation
> updates its private app.config file once all the plugins are parsed
> and all dependencies are collected, and then restart the application
> with the correct redirection of the "core" assemblies of the plug-ins
> side.
>
> It is possible to avoid that and use .policy files even in a non-GAC
> scenario? All the assemblies are strong-named.
One cheap way to avoid the problem is to remove the strong name. I know this
goes against every guideline Microsoft ever wrote, but let's face it: strong
naming doesn't do you a whole lot of good without the ability to publish
policies. All it buys you is the guarantee that either a some system
administrator has had to have signed off on the redirects, or some
programmer has had to have signed off on rebuilding the application to
ensure it still works with the new versions. These are nice guarantees, but
having a working application at all is nicer still.
With some discipline, the same can be achieved without strong naming. You
can still version assemblies without strong names; the versions are just not
enforced by the runtime. You can manually verify the version numbers for
compatibility if you're so inclined, using the attributes of Assembly.
The other benefit strong naming provides (a guarantee that the assembly was
signed by the right party and not tampered with) is often not important when
you are in full control of the distribution, though it might become a
problem in an ecosystem with third-party publishers.
The distinct *drawback* of strong naming on out-of-GAC assemblies, by the
way, is a startup cost of the runtime having to compute the hash of the
assembly to verify the strong name. It can't cache it like it can with
assemblies in the GAC, because they're not in a trusted location. You'd need
to have a lot of assemblies before this becomes noticeable, but if you're
loading them from remote folders, it might become noticeable sooner.
Finally, it's possible to have your cake and eat it too, but not without
significant cost: if you really, really want to have strong-named, versioned
assemblies without the GAC, you can build your own assembly resolution and
loading logic as part of a custom CLR host. However, hosting the runtime
yourself is not for the faint of heart, and requires a good deal of C++.
--
J.