c# - How can I load two versions of same assemblies into two different domains from two different subfolders? -


i'm trying build small tool comparing types in bunch of assemblies. purpose created 2 subfolders , put respective dlls there:

  • ..\dlls\v1.1
  • ..\dlls\v1.2

where .. application folder

i created proxy object:

public class proxydomain : marshalbyrefobject {     public assembly loadfile(string assemblypath)     {         try         {             //debug.writeline("currentdomain = " + appdomain.currentdomain.friendlyname);             return assembly.loadfile(assemblypath);         }         catch (filenotfoundexception)         {             return null;         }     } } 

and used loading in following routine should load dll , types declared in it:

private static hashset<type> loadassemblies(string version) {     _currentversion = version;      var path = path.combine(environment.currentdirectory, path.combine(_assemblydirectory, version));      var appdomainsetup = new appdomainsetup     {         applicationbase = environment.currentdirectory,          };      var evidence = appdomain.currentdomain.evidence;     var appdomain = appdomain.createdomain("appdomain" + version, evidence, appdomainsetup);                 var proxydomaintype = typeof(proxydomain);     var proxydomain = (proxydomain)appdomain.createinstanceandunwrap(proxydomaintype.assembly.fullname, proxydomaintype.fullname);     _currentproxydomain = proxydomain;      var assemblies = new hashset<type>();      var files = directory.getfiles(path, "*.dll");      foreach (var file in files)     {         try         {             var assembly = proxydomain.loadfile(file);             if (assembly != null)             {                 assemblies.unionwith(assembly.definedtypes.where(t => t.ispublic));             }         }         catch (exception)         {         }     }     return assemblies; } 

so far nothing unusual... didn't work in case (probably because of subfolders) searched bit , found settting in app.config might tried add 2 probing paths:

<runtime>   <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">     <probing privatepath="dlls\v1.1;dlls\v1.2" />   </assemblybinding> </runtime> 

now there wasn't filenotfoundexpections anymore dlls have same names loaded dlls first subdirectory (v1.1) both domains removed , instead tried implement appdomain.currentdomain.assemblyresolve event handler that:

appdomain.currentdomain.assemblyresolve += (sender, e) => {     var path = path.combine(environment.currentdirectory, path.combine(_assemblydirectory, _currentversion));     path = path.combine(path, e.name.split(',').first());     path = path + ".dll";     var assembly = _currentproxydomain.loadfile(path);     return assembly; }; 

but unfortunatelly event handler created infinite loop , calls itself each time tries load dll cannot find. have no more ideas else try.


update-1

as @simonmourier suggested tried use custom .config new appdomains , created 2 more *.configs like:

<?xml version="1.0" encoding="utf-8"?> <configuration>   <startup>     <supportedruntime version="v4.0" sku=".netframework,version=v4.5" />   </startup>   <runtime>     <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">       <probing privatepath="dlls\v1.1" />     </assemblybinding>   </runtime> </configuration> 

i named them v1.1.config , v1.2.config. set new configurationfile property:

var appdomainsetup = new appdomainsetup {     applicationbase = environment.currentdirectory,     configurationfile = path.combine(environment.currentdirectory, string.format("{0}.config", version)),         }; 

i've set option copy output directory copy always ;-)

it didn't work googled , tried suggestion:

appdomain.currentdomain.setdata("app_config_file", appdomainsetup.configurationfile); 

but didn't either. still filenotfoundexception custom configs weren't there.

using setconfigurationbytes method instead had no effect:

var domainconfig = @"     <configuration>         <startup>             <supportedruntime version=""v4.0"" sku="".netframework,version=v4.5"" />         </startup>         <runtime>             <assemblybinding xmlns=""urn:schemas-microsoft-com:asm.v1"">               <probing privatepath=""dlls\{0}"" />             </assemblybinding>         </runtime>     </configuration>";  domainconfig = string.format(domainconfig, version).trim(); var probingbytes = encoding.utf8.getbytes(domainconfig); appdomainsetup.setconfigurationbytes(probingbytes); 

however if call getdata method new appdomain uses custom .config:

debug.writeline("current config: " + appdomain.currentdomain.getdata("app_config_file")); 

it outputs path set via configurationfile


update-2

this confusing. stack trace reveals despite of getdata returs assembly.loadfile still uses original .config:

=== log: bind starts in default load context. log: using application configuration file:

c:[...]\bin\debug\myapp.exe.config

log: using host configuration file: log: using machine configuration file from

c:\windows\microsoft.net\framework\v4.0.30319\config\machine.config.


update-3

ok, did more experimenting , found out implementing @simonmourier suggestion indeed worked. filenotfoundexception wasn't thrown loadfile method in proxydomain class in main method of app. gues assembly , types allowed live within proxydomain context , cannot transfered main domain have tried.

public ienumerable<type> loadfile(string assemblypath) {     //try     {         // does't throw exceptions         var assembly = assembly.loadfile(assemblypath);         // returning assembly or types throw exception in main application         return assembly.definedtypes;     }     //catch (filenotfoundexception)     {       //  return null;     } } 

method in main domain:

private static hashset<type> loadassemblies(string version) {     // omitted      foreach (var file in files)     {         //try         {              // exception occurs here, when transfering types between domains:             var types = proxydomain.loadfile(file);                      assemblies.unionwith(types.where(t => t.ispublic));         }     }      // omitted } 

i'll need rewrite comparison algorithm @ least assemblies can loaded ;-)

if don't want recompile assemblies different strong name, can load them different appdomains, different setup configuration, , different .config files, iis multiple web sites, each 1 in 1 appdomain, independent, hosted in 1 apppool process - w3wp.exe.


Comments

Popular posts from this blog

html - Outlook 2010 Anchor (url/address/link) -

javascript - Why does running this loop 9 times take 100x longer than running it 8 times? -

Getting gateway time-out Rails app with Nginx + Puma running on Digital Ocean -