views:

69

answers:

3

For complete separation/decoupling, I've implemented a DAL in an assebly that is simply being copied over via post-build event to the website BIN folder. The website then on Application Start loads that assembly via System.Reflection.Assembly.LoadFile. Again, using reflection, I construct a couple of instances from classes in that assembly. I then store a reference to these instances in the session (HttpContext.Current.Items)

Later, when I try to get the object stored in the session, I am not able to cast them to their own types (was trying interfaces initially, but for debugging tried to cast to THEIR OWN TYPES), getting this error:

 [A]DAL_QSYSCamper.NHibernateSessionBuilder cannot be cast to [B]
DAL_QSYSCamper.NHibernateSessionBuilder. Type A originates from 'DAL_QSYSCamper, 
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at 
location 'C:\Users\myusername\AppData\Local\Temp\Temporary ASP.NET 
Files\root\ad6e8bff\70fa2384\assembly\dl3\aaf7a5b0\84f01b09_b10acb01\DAL_QSYSCamper.DLL'. 
Type B originates from 'DAL_QSYSCamper, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=null' in the context 'LoadNeither' at 
location 'C:\Users\myusername\Documents\Projects\QSYS\Deleteme\UI\MVCClient\bin\DAL_QSYSCa
mper.DLL'.

This is happening while debugging in VS - VS manages to stop into the source DAL project even though I've loaded from assembly and the project is not refferenced by the website project (they're both in the solution).

I do understand the error, but I don't understand how and why the assembly is being used/loaded from two locations - I only load it once from the file and there's no referrence to the project.

Should mention that I also use Windsor for DI. The object that tries to extract the object from the session is A) from a class from that DAL assembly; B) is injected into a website class by Windsor. I will work on adding some sample code to this question, but wanted to put it out in case it's obvious what I do wrong.

+1  A: 

Unless I have misunderstood something about your question by definition casting to the same class from a different assembly is NOT casting to the same class. Assembly1.Class <> Assembly2.Class even if the elements/methods/interfaces and properties are the same.

The only way such a ‘cast’ will succeed (to my knowledge) is thru serialization. Ensure in your project when you are referencing any assembly that you wish to cast it is referenced to the same location and also delete any duplicate object code and host it in a single location.

Maxim Gershkovich
Just to follow up, I suggest deleting all files that are mentioned in the details above, running a clean and recompiling. Also (again I mention) ensure that you do not have the same object in two different locations. Other then that I am out of ideas.
Maxim Gershkovich
Sorry last point, its great to be using a DAL but why use Reflection to load it? Why not just reference it directly?
Maxim Gershkovich
Thank you for taking the time to lookm into my issue.Two points:First, I only load the assembly once, and I don't have a reference to it anywhere else, so, even though I understand what you're saying about two different assemblies - two different classes, I don't understand how I end up with two assemblies (unless it's VS figuring out the project to debug, creating the "temp" one).
G. Stoynev
Second point: Why not reference the DAL assembly? I guess part of it is "why not", "can it be done". Having worked with SCSF and WCSF and not being that experienced, I am trying the idea of creating a "module" that can be plugged in by simply changing the settings... complete decoupling. Learning, I guess.
G. Stoynev
+4  A: 

The reason is given in the Remarks section of the Assembly.LoadFile() method:

Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly.

That's a bit dense perhaps. The assembly loading context is a tricky subject blogged about at length by Suzanne Cook. The ultimate effect is that when you use the types of that assembly elsewhere, you'll get the assembly loaded again and those types won't match the types from the LoadFile assembly since the assemblies have a different identity.

As indicated, use Load or LoadFrom to avoid this problem.

Hans Passant
A: 

Thank you, Hans. It is dense, indeed! ... for someone not perfectly familiar with all the concerns involved. Using LoadFrom seems to have eliminated the issue.

G. Stoynev