What about trying to avoid LoadFrom() all together. i.e. update private bin path and do Load()?
-----Original Message----- From: Dave [mailto:[EMAIL PROTECTED]] Sent: Thursday, December 19, 2002 8:23 AM To: [EMAIL PROTECTED] Subject: [ADVANCED-DOTNET] Assembly isolation http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx My development team has stumbled into a problem that's described by this article. Our app uses plug-in assemblies for specialized functionality; each one is located in a separate subdirectory below the main app directory. One of these has a static dependency to another plugin, so that the resultant directory and file layout looks like... AppBase ---- Plugin1Dir ---- Plugin1.dll ---- Plugin2Dir ---- Plugin2.dll ---- Plugin1.dll Each plugin is signed with a strongname. The main app does not know in advance which of these has been purchased or installed so it does not make any assumptions about what is there and it does not consider load order dependencies. The main app uses the AssemblyResolve event to find referenced assemblies in the subdirectories. Plugin1 uses a web service, so the first time it connects to the web service a proxy assembly is emitted by the runtime and loaded into the app domain. When the app does a LoadFrom on Plugin1Dir/Plugin1.dll the runtime loads it into the appdomain as a path-based reference. When the LoadFrom is done on Plugin2Dir/Plugin2.dll it loads Plugin1.dll again into the app domain, this time as a static reference, so that Plugin1.dll is loaded twice into the appdomain. Because both instances of the Plug1in.dll are loaded in the same appdomain they each use the same proxy dll to access the web service. When a web service call is made from the second instance of Plugin1.dll and which returns a data type defined in Plugin1.dll the runtime throws an exception. It cannot cast the return value to the type defined in the second instance of Plugin1.dll because the proxy has that type as being defined in the first instance of Plugin1.dll, so it treats them as two different types. There are several workarounds to this problem. The easy short-term fix was to simply delete the Plugin1.dll that is in the Plugin2Dir - when the runtime fails to locate it an AssemblyResolve event is triggered, so the resolver can tell it to use the assembly in Plugin1Dir. This is not a useful long-term solution because it is too fragile. One longterm solution is to load each plugin into a separate appdomain - this means rewriting and testing each one as all objects will have to be remoted from each appdomain, but it is probably the way we will go. However, this does not guarantee a fix in all cases because each plugin may itself do a LoadFrom and/or have static references to other assemblies - the problem may be recursive. Another is to have the app analyze all plugins and load those with static references to other plugins first, but again the problem may be recursive, so each plugin might have to implement similar logic. Is there some way to override the default behavior of the runtime so that it can be forced to use the path-based reference that is already loaded into the appdomain instead of loading a second image of the assembly to satisfy a static reference? The runtime does not generate the Resolve event if it satisfies the reference request, so I cannot override the static reference with the path-based reference because my code never gets invoked. My thought is that for assemblies signed with a strongname the runtime could have a mode so that in cases where the full names of the assembly match, a static reference is satisfied by a path based reference (and vice- versa). Another is to add an event that allows code to get involved in the static reference resolution process. Thoughts? Any better way to handle this? and thanks in advance. You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com. This message is for the named person's use only. It may contain sensitive and private proprietary or legally privileged information. No confidentiality or privilege is waived or lost by any mistransmission. If you are not the intended recipient, please immediately delete it and all copies of it from your system, destroy any hard copies of it and notify the sender. You must not, directly or indirectly, use, disclose, distribute, print, or copy any part of this message if you are not the intended recipient. CREDIT SUISSE GROUP and each legal entity in the CREDIT SUISSE FIRST BOSTON or CREDIT SUISSE ASSET MANAGEMENT business units of CREDIT SUISSE FIRST BOSTON reserve the right to monitor all e-mail communications through its networks. Any views expressed in this message are those of the individual sender, except where the message states otherwise and the sender is authorized to state them to be the views of any such entity. Unless otherwise stated, any pricing information given in this message is indicative only, is subject to change and does not constitute an offer to deal at any price quoted. Any reference to the terms of executed transactions should be treated as preliminary only and subject to our formal written confirmation. You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced DOTNET, or subscribe to other DevelopMentor lists at http://discuss.develop.com.
