开发者

Assembly unavailable after Web.config change

开发者 https://www.devze.com 2022-12-26 03:09 出处:网络
I\'m using a custom framework that uses reflection to do a GetTypeByName(string fullName) on the fully-qualified type name that it gets from the database, to create an instance of said type and add it

I'm using a custom framework that uses reflection to do a GetTypeByName(string fullName) on the fully-qualified type name that it gets from the database, to create an instance of said type and add it to the page, resulting in a standard modular kind of thing.

GetTypeByName is a utility function of mine that simply iterates through Thread.GetDomain().GetAssemblies(), then performs an assembly.GetType(fullName) to find the relevant type. Obviously this result gets cached for future reference and speed.

However, I'm experiencing some issues whereby if the web.config gets updated (and, in some scarier instances if the application pool gets recycled) then it will lose all knowledge of certain assemblies, resulting in the inability to render an instance of the module type. Debugging shows that the missing assembly literally does not exist in the current thread assemblies list.

To get around this I added a second check which is a bit dirty but recurses through the /bin/ directory's DLLs and checks that each one exists in the assemblies list. If it doesn't, it loads it using Assembly.Load and fixing the context issue thanks to 'Solving the Assembly Load Context Proble开发者_开发问答m'.

This would work, only it seems that (and I'm aware this shouldn't be possible) some projects still have access to the missing assembly, for example my actual web project rather than the framework itself - and it then complains that duplicate references have been added!

Has anyone ever heard of anything like this, or have any ideas why an assembly would simply drop out of existence on a config change? Short of a solution, what is the most elegant workaround to get all the assemblies in the bin to reload? It needs to be all in one "hit" so that the site visitors don't see any difference other than a small delay, so an app_offline.htm file is out of the question. Programatically renaming a DLL in the bin and then naming it back does work, but requires "modify" permissions for the IIS user account, which is insane.

Thanks for any pointers the community can gather!


Generally, you should avoid relying on what assemblies are currently loaded in an appdomain, as that happens dynamically. Instead, simply call System.Web.Compilation.BuildManager.GetType() instead of Type.GetType() or Assembly.GetType(). This should just do the right thing for you, and not be affected by appdomain cycles.


As you obviously know, there are many situations where the current appdomain is unloaded and reloaded. After each reload, all assemblies are unloaded and the whole application starts running "from scratch".

Assemblies are by default loaded on demand. Usually that is the case when the JIT stumbles across some reference. In consequence, a appdomain reload will clear out the assemblies in the appdomain and they will only appear again later on when the JIT loads them.

As solution I'd rever to using the static Type.GetType() method and supply an assembly qualified name (e.g. a type name with the assembly name included). That's the same thing the framework uses when loading types specified in the config file, and it will make sure that the required assembly is searched and loaded on demand without using any tricks. See the remarks section of the method above (the method name above name is a link).

This will require updates to your database to hold assembly qualified names instead of "only" fully qualified type names. However, it also makes sure that you don't run into name collisions when two assemblies provide different type with the same name, so this is a good idea anyways I think.


I've never heard of this problem before.

I'm not sure if this will work, as I only recently read about it while researching workarounds to ODAC dependencies, but specifying the probing path for assemblies may fix your issue.

see: http://msdn.microsoft.com/en-us/library/823z9h8w(VS.80).aspx

sample:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="bin;bin2\subbin;bin3"/>
      </assemblyBinding>
   </runtime>
</configuration>


I have a similar problem, when I update 2-5 files, ether web.config, ether other files, and asp.net needs to recreate the running files, then some times did not find some classes/function that exist on dll files, and my system is not working - throw errors like yours.

My solution to that is that I place the app_offline.htm on the root, make my updates, then rename/remove the app_offline.htm and my system works fine.

I am sure that have something to do with the cached compiled files, but I did not have deaply search whats exactly cause that.

[what is the most elegant workaround to get all the assemblies in the bin to reload]

Now what is the most elegant workaround on this is to call the HttpRuntime.UnloadAppDomain and actually make your application to stop and starts again.

http://msdn.microsoft.com/en-us/library/system.web.httpruntime.unloadappdomain(VS.80).aspx

I do not know if this solve your issue, you need to make tests.

probably on Global.asax make something like that

void Application_Error(object sender, EventArgs e) 
{
   Exception ex = Server.GetLastError().GetBaseException();
   ...if ex is your error, and you get more than 2 ...
   {
     HttpRuntime.UnloadAppDomain();
   }
}


I would try to create some basic class from which assembly, which is interesting for you without reflection on Application Start to make sure it is loaded. E.g.

var temp = new BaseModuleBuilder();

This do not look smart, but it is very straitforward and asp.net should do everything for you. In case when your list is too dynamic, it could be something like

var temp = Activator.CreateInstance(Type.GetType("BaseModuleBuilder, Modules.dll"));

Make sure to always specify DLL when working with dynacmically loaded classes.

0

精彩评论

暂无评论...
验证码 换一张
取 消