Assembly.Load() followed by Assembly.LoadFrom()?


Assembly.Load() takes an assembly display name as input, while Assembly.LoadFrom() takes a file path as input.


 


Typically the application will only call one of them, but not one after the other.


 


I have seen a few cases where people want to do an Assembly.Load(). If that fails they will re-try with Assembly.LoadFrom().


 


The usual case is that the application gets the input from somewhere, could be user input, or a string from database etc. But the application has no idea whether the input is a display name or a file path. So it does the fall back thing.


 


A design that can not distinguish a display name from a file path does not sound like a good design to me. But understood that sometimes there is no choice.


 


But you still have several different ways to do the fallback.


 



  1. call File.Exists() on the input. If that succeeds, assume it is a file and call Assembly.LoadFrom(). Otherwise, assume it is a display name and call Assembly.Load().

  2. call Assembly.Load(), if that fails, try Assembly.LoadFrom().

  3. call Assembly.Load(), and hook up AssemblyResolveEvent to fallback to Assembly.LoadFrom()

  4. call Assembly.LoadFrom(), if that fails, try Assembly.Load().

 


Personally I favor 1). But if the input is a URL then you can’t use 1).


 


2) and 3) have subtle differences.


 


In 2) you have to catch an exception returned from Assembly.LoadFrom(). In 3) you may not need.


 


On the other hand, 3) will affect every other unrelated Assembly.Load(). More importantly, the display name you get in the ResolveEventArgs is not the original one. It has been processed by fusion, which may or may not be the same as the original one.


 


That is, I definitely prefer 2) over 3).

Comments (11)

  1. Leon says:

    Hi,

    I couldn’t find any working comments page. So I found this closely related post and putting my comments here :)

    Could you please clarify the following:

    1. In .NET 1.1 if I use Assembly.Load(byte[]), is there any code/data sharing between successive Assembly.Load calls in same or other AppDomain? I mean the kind of sharing that is done by win32 dll loader.

    2. Same question as 1, but also does new IHostAssemblyStore provide any advantage here (memory sharing related and more)?

    Thank you very much for any help!

  2. junfeng says:

    1. No it will not be shared.

    2. IHostAssemblyStore does not provide any advantage here. It is meant for SQLServer type of storage where the assembly physically exists in a database as bytes.

  3. Leon says:

    Thank you for the comments.

    Would you mind answering CLR hosting and assembly binding relatedt questions?

    I’m trying new CLR 2.0 hosting API.

    1. I’ve provided IHostAssemblyManager impl to CLR.

    2. I’m calling ExecuteInDefaultAppDomain(assemblyPath,…)

    Now the questions is:

    Why when I implement GetNonHostStoreAssemblies and return ICLRAssemblyReferenceList implementation, ExecuteInDefaultAppDomain fails to find the assembly. But if I set *ppReferenceList = NULL; in GetNonHostStoreAssemblies, it calls IHostAssemblyStore::ProvideAssembly.

    Neither IHostAssemblyStore::ProvideAssembly/ICLRAssemblyReferenceList::IsAssemblyReferenceInList/LRAssemblyReferenceList::IsStringAssemblyReferenceInList are called when it fails for ExecuteInDefaultAppDomain. But they are called for example when CLR needs to find my custom AppDomainManager. Is this a bug or standard behavior for ExecuteInDefaultAppDomain?

    Thanks a lot!

  4. junfeng says:

    You need to read Steven’s book on this

    http://blogs.msdn.com/junfeng/archive/2005/06/17/430342.aspx

    It is a big topic.

  5. Leon says:

    Thank you for the book recomendation. I will buy it. I’m pretty familiar with how it works in .NET 1.1. I hope the book covers new hosting API/AssemblyStore and my question.

    But briefly could you please just say if what I’m seeing is normal?

    Assembly specified in ExecuteInDefaultAppDomain doesn’t go through IHostAssemblyStore::ProvideAssembly when I return my own ICLRAssemblyReferenceList implementation. And does go through IHostAssemblyStore::ProvideAssembly when I don’t return ICLRAssemblyReferenceList implementation in GetNonHostStoreAssemblies.

  6. junfeng says:

    We call IHostAssemblyStore::ProvideAssembly when the assembly is *not* in the list of GetNonHostStoreAssemblies.

    When GetNonHostStoreAssemblies returns NULL, we probe GAC, then IHostAssemblyStore, finally appbase.

    There is a Matrix our test team uses. I’ll see if I can still find it.

  7. Leon says:

    But what I’m seeing is that ICLRAssemblyReferenceList is not consulted for the assembly specified in ExecuteInDefaultAppDomain when I return valid ICLRAssemblyReferenceList pointer from GetNonHostStoreAssemblies. And is consulted when I return null for ICLRAssemblyReferenceList pointer. This is on Beta 2.

    It will be time consuming to create a repro sample for this if it’s not a bug, but standard behavior. Otherwise I could report it.

  8. Leon says:

    I saw from the docs:

    "Remarks

    The common language runtime resolves references using the following set of guidelines.

    First, it consults the list of assembly references returned by GetNonHostStoreAssemblies.

    If the assembly appears in the list, the runtime binds to it normally.

    If the assembly does not appear in the list, and the host has provided an implementation of IHostAssemblyStore, the runtime calls IHostAssemblyStore::ProvideAssembly to allow the host to supply the assembly to bind to.

    Otherwise, the runtime fails to bind the assembly.

    If the host sets ppReferenceList to NULL, the runtime first probes the Global Assembly Cache, then calls ProvideAssembly, then probes the application base, to resolve an assembly reference.

    Note: The runtime calls GetNonHostStoreAssemblies only once, upon initialization. It is not called again."

    But I don’t see loader consulting list of assembly references returned by GetNonHostStoreAssemblies for assembly specified in ExecuteInDefaultAppDomain. But it is consulted when I return ppReferenceList = NULL; from GetNonHostStoreAssemblies. So, I’m just trying to find out if this a bug or not.

  9. junfeng says:

    It could be some mistake in your code. I can’t really tell from this thread so far.

    It could be a bug in CLR but this is very unlikely. Otherwise SQL folks will be chasing my back every minutes:)

    Please report it in MSDN feedback center.

  10. Leon says:

    Thank you for the book. I haven’t seen that title before.