About assembly. Unload

Source: Internet
Author: User
It seems that only the favorites are available. Good news, plug-in, and this article Article It's critical to just hold your throat! Flier has just moved to cnblogs and has less temperature. I think one-by-one must be very familiar with him. Nice

Http://www.cnblogs.com/flier/archive/2004/07/08/22382.aspx
Http://www.blogcn.com/user8/flier_lu/index.html? Id = 2164751 & run = blogcn

CLR product unit manager Jason Zander wrote a previous article about Why isn' t there an assembly. Unload method? It explains why there is no assembly. Unload method similar to the unloadlibrary function in Win32 API.
He believes that the main purpose of implementing the Assembly. Unload function is to reclaim space and update versions. The former recycles the resources it occupies after using the assembly, and the latter uninstalls the current version and loads the updated version. For example, the Assembly used for pages in ASP. NETProgramDynamic Update is a good example. However, if the Assembly. Unload function is provided, some problems may occur:

1. to wrap the CLRCodeThe referenced Code addresses are valid. special applications such as GC objects and com ccw must be tracked. Otherwise, the code or data address of the Assembly is used by the CLR object or COM component after the Assembly is unloaded, resulting in access exceptions. To avoid such errors, tracking is currently performed at the appdomain level. if unload is supported, the tracking granularity must be reduced to the Assembly level. This is not technically impossible, but it is too costly.

2. If you support assembly. Unload, you must track the handles used by each assembly code and reference existing hosted code. For example, when jiter compiles a method, the generated code is in a unified region. To uninstall an assembly, each assembly must be compiled independently. In addition, there are some similar resource usage problems. If it is feasible to separate tracing technology, it is costly, especially for systems with limited resources such as wince.

3. CLR supports cross-appdomain assembly loading optimization, that is, domain neutral optimization, so that multiple AppDomains can share one piece of code to speed up loading. Currently, V1.0 and V1.1 Cannot uninstall domain neutral code. This also leads to the difficulty of implementing the complete semantics of Assembly. Unload.

Based on the above problems, Jason Zander recommends other design methods to avoid using this function. For example, the appdomain and Shadow Copy introduced by Junfeng Zhang on his blog is a method for ASP. NET to solve similar problems.

When constructing an appdomain, The appdomain. appdomainsetup in the appdomainsetup parameter of the createdomain method. set shadowcopyfiles to "true" to enable the shadowcopy policy, and then set appdomainsetup. shadowcopydirectories is the target directory for replication; Set appdomainsetup. cachepath + appdomainsetup. applicationname specifies the cache path and file name.
This method can simulate the semantics of Assembly. Unload. The implementation is to load the assembly to be managed into a dynamically created appdomain, then call its function through a transparent proxy across appdomain, and use appdomain. Unload to simulate the semantics of Assembly. Unload. Chornbe provides a simple packaging class. For the code, see the end of the article.

Although this can be basically simulated in terms of semantics, there are many problems and costs:

1. Performance: In CLR, appdomain is similar to the logic concept of operating system processes. Cross-appdomain communication is subject to many restrictions as in the past. Although transparent proxy objects can be used to call a cross-process COM Object and automatically complete parameter financialing operations, a considerable cost must be paid. In the example given by Dejan jelovic (cross-appdomain CILS are extremely slow), it takes about 1 ms to use only the built-in call type for P4 1.7g. This is too costly for some functions that require frequent calls. As he mentioned, it takes 200 ms to draw 200 points in onpaint. Although optimization can be performed by batch calling, the penalty for cross-appdomain calling efficiency cannot be escaped. Fortunately, it is said that in Whidbey, the built-in types in the Cross-appdomain call can be optimized without marshal, so that the call speed is more than seven times faster than the existing implementation ,..., I don't know how to praise Whidbey for its implementation, but I am still jealous of the bad version.

2. ease of use: The types in the Assembly that need to be detached separately may not support marshal. In this case, you need to manage the types by yourself.

3. Version: in multiple AppDomains, how does one wrap the correctness of version loading.

In addition, there are security issues. For a common assembly. for load, the loaded Assembly runs under the evidence of the loader, which is definitely a security risk, attackers may suffer from attacks similar to Unix that overwrite the system file by using the root permission to read and write files. When an assembly is loaded in an appdomain, CAS permissions can be set separately to reduce execution permissions. Because of the four-level permission control mechanism in the CLR architecture, the minimum granularity can only be appdomain. Fortunately, it is said that Whidbey will be added to support loading assembly with different evixes.

Through these discussions, we can see that the semantic existence of Assembly. Unload is very important for plug-in-based programs. However, in recent versions, it is more appropriate to simulate the semantics of appdomain. Although performance and ease of use are required, however, it can control functions, security, and other factors to a greater extent. In the long run, assembly. the implementation of unload is completely feasible. The best example of uninstalling classes in Java is that the previous reasons are actually workload and complexity issues, and there are no technical problems that cannot be solved.

# Re: appdomain and Shadow Copy4/30/2004 AMChornbe

You must also encapsulate the loaded assembly into another class, which is loaded by the new appdomain. here's the Code as it's working for me: (I 've created a few M exception types, and you'll notice I had them back-They're not descended from your albyrefobject so I can't just throw them from the encapsulated code)

--- Cut first class file
Using system;
Using system. reflection;
Using system. collections;

Namespace loader {

/* Contains Assembly loader objects, stored in a hash
* And keyed on the. dll file they represent. Each assembly Loader
* Object can be referenced by the original name/path and is used
* Load objects, returned as type object. It is up to the calling class
* To cast the object to the necessary type for consumption.
* External interfaces are highly recommended !!
**/
Public class objectloader: idisposable {

// Essentially creates a parallel-Hash pair setup
// One appdomain per Loader
Protected hashtable domains = new hashtable ();
// One loader per Assembly DLL
Protected hashtable loaders = new hashtable ();

Public objectloader (){/*...*/}

Public object GetObject (string dllname, string typename, object [] constructorparms ){
Loader. assemblyloader Al = NULL;
Object o = NULL;
Try {
Al = (loader. assemblyloader) loaders [dllname];
} Catch (exception ){}
If (Al = NULL ){
Appdomainsetup setup = new appdomainsetup ();
Setup. shadowcopyfiles = "true ";
Appdomain domain = appdomain. createdomain (dllname, null, setup );
Domains. Add (dllname, domain );
Object [] parms = {dllname };
// Object [] parms = NULL;
Bindingflags bindings = bindingflags. createinstance | bindingflags. instance | bindingflags. Public;
Try {
Al = (loader. assemblyloader) domain. createinstancefromandunwrap (
"Loader. dll", "loader. assemblyloader", true, bindings, null, parms, null
);
} Catch (exception ){
Throw new assemblyloadfailureexception ();
}
If (Al! = NULL ){
If (! Loaders. containskey (dllname )){
Loaders. Add (dllname, Al );
} Else {
Throw new assemblyalreadyloadedexception ();
}
} Else {
Throw new assemblynotloadedexception ();
}
}
If (Al! = NULL ){
O = Al. GetObject (typename, constructorparms );
If (o! = NULL & O is assemblynotloadedexception ){
Throw new assemblynotloadedexception ();
}
If (O = NULL | o is objectloadfailureexception ){
String MSG = "Object cocould not be loaded. Check that type name" + typename +
"And constructor parameters are correct. Ensure that type name" + typename +
"Exists in the assembly" + dllname + ".";
Throw new objectloadfailureexception (MSG );
}
}
Return O;
}

Public void unload (string dllname ){
If (domains. containskey (dllname )){
Appdomain domain = (appdomain) domains [dllname];
Appdomain. Unload (domain );
Domains. Remove (dllname );
}
}

~ Objectloader (){
Dispose (false );
}

Public void dispose (){
Dispose (true );
}

Private void dispose (bool disposing ){
If (disposing ){
Loaders. Clear ();
Foreach (Object o in domains. Keys ){
String dllname = O. tostring ();
Unload (dllname );
}
Domains. Clear ();
}
}
}

}

--- End cut

--- Cut second class file
Using system;
Using system. reflection;

Namespace loader {
// Container for assembly and exposes a GetObject function
// To create a late-bound object for Casting by the consumer
// This class is meant to be contained in a separate appdomain
// Controlled by objectloader class to allow for proper Encapsulation
// Which enables proper shadow-copying functionality.
Internal class assemblyloader: externalbyrefobject, idisposable {

# Region class-level declarations
Private Assembly A = NULL;
# Endregion

# Region constructors and Destructors
Public assemblyloader (string fullpath ){
If (A = NULL ){
A = assembly. loadfrom (fullpath );
}
}
~ Assemblyloader (){
Dispose (false );
}

Public void dispose (){
Dispose (true );
}

Private void dispose (bool disposing ){
If (disposing ){
A = NULL;
System. gc. Collect ();
System. gc. waitforpendingfinalizers ();
System. gc. Collect (0 );
}
}
# Endregion

# Region Public functionality
Public object GetObject (string typename, object [] ctorparms ){
Bindingflags flags = bindingflags. createinstance | bindingflags. instance | bindingflags. Public;
Object o = NULL;
If (! = NULL ){
Try {
O = A. createinstance (typename, true, flags, null, ctorparms, null, null );
} Catch (exception ){
O = new objectloadfailureexception ();
}
} Else {
O = new assemblynotloadedexception ();
}
Return O;
}
Public object GetObject (string typename ){
Return GetObject (typename, null );
}
# Endregion

}
}
--- End cut

Related Resources:
Why isn't there an assembly. Unload method?
Http://blogs.msdn.com/jasonz/archive/2004/05/31/145105.aspx

AppDomains ("application domains ")
Http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx

Create a trickle-feed Application
Http://www.fawcette.com/vsm/2002_07/magazine/features/thomas/default_pf.aspx

Appdomain and Shadow Copy
Http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.