I'm trying to determine if MEF is a the proper direction our application framework should be taking. From my reading of MEF, our framework doesn't seem to 'exactly' fit in, but I'll see if any experts can guide me.
Our framework allows us to have one core website and dependent assemblies deployed to one place (and fixes or features are propogated to all clients), then we have client websites that kind of 'merge' into the core website and extend it where needed.
Now in IIS, each client site is its own application running in its own AppDomain. However, every application has the same physical path pointing at the 'core website'.
So our file structure is...
- /CoreSite
- /bin (containing core site and dependency dlls)
- /[Core site folders] (e.g. Models, Views, Controlers, Content, etc.)
- /Clients
- /_Assemblies (containing all the client assemblies - 100s of clients)
- /Client1
- /[Client site folders] (e.g. Models, Views, Controllers, etc.)
- /Client2
- /[Client site folders] (e.g. Models, Views, Controllers, etc.)
- /ClientN
So as you may have guessed, assembly loading is our issue. We didn't want to put all the client assemblies into the root /bin folder for a couple reasons. First we didn't want each client site to load every other clients assembly. Secondly, we didn't want every site's AppDomain to be recycled simply because another client's assembly was updated in the /bin folder.
To make this work in asp.net 1.1, we followed http://www.hanselman.com/blog/MovingTheCodeBehindAssembliesDLLsToADifferentFolderThanBINWithASPNET11.aspx and added the <probing privatePath="bin;Clients/_Assemblies"/> element in the web.config along with the <%@ Assembly Name="ClientN" %> directive in each view in the client sites. The only other problem we had to overcome was updating the client assemblies, but asp.net 1.1 would lock the assemblies in /Clients/_Assemblies directory. We simply added:
if ( Directory.Exists( assembliesDir ) && AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories.IndexOf( assembliesDir ) < 0 )
{
AppDomain.CurrentDomain.SetShadowCopyPath( AppDomain.CurrentDomain.SetupInformation.ShadowCopyDirectories + ";" + assembliesDir );
}
And viola, everything seemed to work like a charm. Unfortunately in asp.net 4.0, AppDomain.CurrentDomain.SetShadowCopyPath() has been deprecated. So we've been messing around with trying to lo开发者_如何学Cad assemblies ourself from a byte array, attempted to use AssemblyResolve event, have messed around in the [assembly: PreApplicationStartMethod( typeof( MvcApplication ), "PreApplicationStart" )], have tried using System.Compilation.BuildManager.AddReferencedAssembly to no avail.
We either get: - no assembly loaded - too many assemblies loaded, or - the assembly gets loaded but when a view is rendering and encounters a <Import/> directive where the namespace should have located from <%@ Assembly Name="ClientN" %> simply fails.
So I'm asking for any suggestions using any mechanism and/or advice on whether MEF is the way to go. My 1000 foot view is that MEF is geared more towards 1 application (and or website) that has several components plug into it. I'm hesitant to start a major code refactor (it seems) because in our situation, we only ever have one component plug into it at a time per application/appdomain. It also seems to do a lot more than what we need it to (simply get the assembly loaded and have asp.net recognize it...then all our code will work).
Any advice is greatly appreciated.
It looks like what you need to do is figure out how to enable shadow copying for all of the folders you have assemblies in. The reason the method you were using is deprecated is because you really need to set this before the AppDomain is created. So my guess is there's probably something you need to set up in your web.config to enable this.
MEF might or might not be a good fit for your application, but it won't solve the shadow copying issue.
According to the documentation the behavior has changed since .NET 2.0. All assemblies found through probing (this includes private path) are automatically subject to shadow copying (of cause it is enabled for an app domain) and the SetShadowCopyPath method has inverse goal - it narrows shadow copying path.
By default, a shadow copy includes all assemblies found through probing. The SetShadowCopyPath method restricts the shadow copy to the assemblies in the directories specified by path.
The SetShadowCopyPath method does not specify additional directories to be searched for assemblies. Assemblies to be shadow-copied must already be located in the search path, for example under BaseDirectory. The SetShadowCopyPath method specifies which search paths are eligible to be shadow-copied.
精彩评论