Tải bản đầy đủ - 0 (trang)
4 Create a Type That Can't Cross Application Domain Boundaries

4 Create a Type That Can't Cross Application Domain Boundaries

Tải bản đầy đủ - 0trang

documentationforalistofclassesderivedfromMarshalByRefObject.)



3.5LoadanAssemblyintotheCurrent

ApplicationDomain

Problem

Youneedtoloadanassemblyatruntimeintothecurrentapplication

domain.



Solution

UsethestaticLoadorLoadFrommethodsofthe

System.Reflection.Assemblyclass.



Discussion

TheCLRwillautomaticallyloadtheassembliesidentifiedatbuildtimeas

beingreferencedbyyourassembly.However,youcanalsoexplicitly

instructtheruntimetoloadassemblies.TheLoadandLoadFrom

methodsbothresultintheruntimeloadinganassemblyintothecurrent

applicationdomain,andbothreturnanAssemblyinstancethat

representsthenewlyloadedassembly.Thedifferencebetweeneach

methodistheargumentsthatyoumustprovidetoidentifytheassembly

toload,andtheprocessthattheruntimeundertakestolocatethe

specifiedassembly.

TheLoadmethodprovidesoverloadsthatallowyoutospecifythe

assemblytoloadusingoneofthefollowing:

Astringcontainingthefullyorpartiallyqualifieddisplaynameof

theassembly

ASystem.Reflection.AssemblyNamecontainingdetailsofthe

assembly

Abytearraycontainingtherawbytesthatconstitutetheassembly

Mostoften,youwilluseadisplaynametoloadanassembly.Afully

qualifieddisplaynamecontainstheassembly'stextname,version,



culture,andpublickeytoken,separatedbycommas(forexample,

System.Data,Version=1.0.5000.0,Culture=neutral,

PublicKeyToken=b77a5c561934e089).Tospecifyanassemblythat

doesn'thaveastrongname,usePublicKeyToken=null.Youcanalso

specifyapartialdisplayname,butasaminimum,youmustspecifythe

assemblyname(withoutthefileextension).Thefollowingcode

demonstratesvarioususesoftheLoadmethod.

//LoadtheSystem.Dataassemblyusingafully

//qualifieddisplayname.

stringname1="System.Data,Version=1.0.5000.0,"+

"Culture=neutral,PublicKeyToken=b77a5c561934e089";

Assemblya1=Assembly.Load(name1);

//LoadtheSystem.XmlassemblyusinganAssemblyName.

AssemblyNamename2=newAssemblyName();

name2.Name="System.Xml";

name2.Version=newVersion(1,0,5000,0);

name2.CultureInfo=newCultureInfo("");

name2.SetPublicKeyToken(

newbyte[]{0xb7,0x7a,0x5c,0x56,0x19,0x34,0xe0,0x89});

Assemblya2=Assembly.Load(name2);

//LoadtheSomeAssemblyassemblyusingapartialdisplayname

Assemblya3=Assembly.Load("SomeAssembly");

InresponsetotheLoadcall,theruntimeundertakesanextensive

processtolocateandloadthespecifiedassembly.Here'sasummary;

consultthe.NETFrameworkSDKdocumentationformoredetails.

1. Ifyouspecifyastrong-namedassembly,theLoadmethodwill

applyversionpolicyandpublisherpolicytoenablerequestsfor

oneversionofanassemblytobesatisfiedbyanotherversion.

Versionpolicyisspecifiedinyourmachineorapplication

configurationfileusingelements.Publisher

policyisspecifiedinspecialresourceassembliesinstalledinto

theglobalassemblycache(GAC).

2. Oncetheruntimehasestablishedthecorrectversionofan



assemblytouse,itattemptstoloadstrong-namedassemblies

fromtheGAC.

3. Iftheassemblyisn'tstrongnamedorisn'tfoundintheGAC,the

runtimelooksforapplicableelementsinyour

machineandapplicationconfigurationfiles.A

elementmapsanassemblynametoafileoraURL.Ifthe

assemblyisstrongnamed,canrefertoany

locationincludingInternet-basedURLs;otherwise,

mustrefertoadirectoryrelativetotheapplicationdirectory.If

theassemblydoesn'texistatthespecifiedlocation,Load

throwsaSystem.IO.FileNotFoundException.

4. Iftherearenoelementsrelevanttotherequested

assembly,theruntimewilllocatetheassemblyusingprobing.

Probinglooksforthefirstfilewiththeassembly'sname(with

eithera.dllor.exeextension)inthefollowinglocations:

theapplicationrootdirectory

directoriesbelowtheapplicationrootthatmatchthe

assembly'snameandculture

directoriesbelowtheapplicationrootthatarespecified

intheprivatebinpath

TheLoadmethodistheeasiestwaytolocateandloadassemblies,but

canalsobeexpensiveintermsofprocessingiftheruntimeneedstostart

probingmanydirectoriesforaweak-namedassembly.TheLoadFrom

methodallowsyoutoloadanassemblyfromaspecificlocation.Ifthe

specifiedfileisn'tfound,theruntimewillthrowaFileNotFoundException.

Theruntimewon'tattempttolocatetheassemblyinthesamewayasthe

Loadmethod—LoadFromprovidesnosupportfortheGAC,policies,

elements,orprobing.Thiscodedemonstratesuseofthe

LoadFrommethodtoloadtheassemblynamed

c:\shared\MySharedAssembly.dll.NoticethatunliketheLoadmethod,

LoadFromrequiresthatyouspecifytheextensionoftheassemblyfile.

//Loadtheassemblynamedc:\shared\MySharedAssembly.dll



Assemblya4=Assembly.LoadFrom(@"c:\shared\MySharedAssembly.dl



3.6ExecuteanAssemblyinaDifferent

ApplicationDomain

Problem

Youneedtoexecuteanassemblyinanapplicationdomainotherthanthe

currentone.



Solution

CalltheExecuteAssemblymethodoftheAppDomainobjectthat

representstheapplicationdomain,andspecifythenameofan

executableassembly.



Discussion

Ifyouhaveanexecutableassemblythatyouwanttoloadandruninan

applicationdomain,theExecuteAssemblymethodprovidestheeasiest

solution.TheExecuteAssemblymethodprovidesfouroverloads.The

simplestoverloadtakesonlyastringcontainingthenameofthe

executableassemblytorun;youcanspecifyalocalfileoraURL.Other

ExecuteAssemblyoverloadsallowyoutospecifyevidenceforthe

assembly(seerecipe13.10)andargumentstopasstotheassembly's

entrypoint(equivalenttocommand-linearguments).

TheExecuteAssemblymethodloadsthespecifiedassemblyand

executesthemethoddefinedinmetadataastheassembly'sentrypoint

(usuallytheMainmethod).Ifthespecifiedassemblyisn'texecutable,

ExecuteAssemblythrowsa

System.Runtime.InteropServices.COMException.TheCLRdoesn'tstart

executionoftheassemblyinanewthread,socontrolwon'treturnfrom

theExecuteAssemblymethoduntilthenewlyexecutedassemblyexits.

BecausetheExecuteAssemblymethodloadsanassemblyusingpartial

information(onlythefilename),theCLRwon'tusetheGACorprobingto

resolvetheassembly.(Seerecipe3.5formoreinformation.)

ThefollowingexampledemonstratestheuseoftheExecuteAssembly



methodtoloadandrunanassembly.TheExecuteAssemblyExample

classcreatesanAppDomainandexecutesitselfinthatAppDomainusing

theExecuteAssemblymethod.Thisresultsintwocopiesofthe

ExecuteAssemblyExampleassemblyloadedintotwodifferentapplication

domains.

usingSystem;

publicclassExecuteAssemblyExample{

publicstaticvoidMain(string[]args){



//Forthepurposeofthisexample,ifthisassemblyis

//inanAppDomainwiththefriendlyname"NewAppDomain

//createanewAppDomain.Thisavoidsaninfiniteloop

//AppDomaincreation.

if(AppDomain.CurrentDomain.FriendlyName!="NewAppDoma



//Createanewapplicationdomain

AppDomaindomain=AppDomain.CreateDomain("NewAppDo



//Executethisassemblyinthenewapplicationdom

//passthearrayofcommand-linearguments.

domain.ExecuteAssembly("ExecuteAssemblyExample.exe"

null,args);

}



//Displaythecommand-lineargumentstothescreenpre

//thefriendlynameoftheAppDomain.

foreach(stringsinargs){



Console.WriteLine(AppDomain.CurrentDomain.FriendlyN

":"+s);

}

}

}



3.7InstantiateaTypeinaDifferentApplication

Domain

Problem

Youneedtoinstantiateatypeinanapplicationdomainotherthanthe

currentone.



Solution

CalltheCreateInstanceorCreateInstanceFrommethodofthe

AppDomainobjectthatrepresentsthetargetapplicationdomain.



Discussion

TheExecuteAssemblymethoddiscussedinrecipe3.6isstraightforward

touse,butwhenyouaredevelopingsophisticatedapplicationsthatmake

useofapplicationdomains,youarelikelytowantmorecontroloverthe

loadingofassemblies,instantiationoftypes,andtheinvocationofobject

memberswithintheapplicationdomain.

TheCreateInstanceandCreateInstanceFrommethodsprovideavariety

ofoverloadsthatofferfine-grainedcontrolovertheprocessofobject

instantiation.Thesimplestoverloadsassumeuseofatype'sdefault

constructor,butbothmethodsimplementoverloadsthatallowyouto

provideargumentstouseanyconstructor.

TheCreateInstancemethodloadsanamedassemblyintotheapplication

domainusingtheprocessdescribedfortheAssembly.Loadmethodin

recipe3.5.CreateInstancetheninstantiatesanamedtypeandreturnsa

referencetothenewobjectwrappedinanObjectHandle(describedin

recipe3.3).TheCreateInstanceFrommethodalsoinstantiatesanamed

typeandreturnsanObjectHandlewrappedobjectreference;however,

CreateInstanceFromloadsthespecifiedassemblyintotheapplication

domainusingtheprocessdescribedinrecipe3.5forthe

Assembly.LoadFrommethod.



Tip AppDomainalsoprovidestwoconveniencemethodsnamed

CreateInstanceAndUnwrapandCreateInstanceFromAndUnwrap

thatautomaticallyextractthereferenceoftheinstantiatedobject

fromthereturnedObjectHandleobject;youmustcastthe

returnedobjecttothecorrecttype.

BeawarethatifyouuseCreateInstanceorCreateInstanceFromto

instantiateMBVtypesinanotherapplicationdomain,theobjectwillbe

createdbutthereturnedobjectreferencewon'trefertothatobject.

BecauseofthewayMBVobjectscrossapplicationdomainboundaries,

thereferencewillrefertoacopyoftheobjectcreatedautomaticallyinthe

localapplicationdomain.OnlyifyoucreateanMBRtypewillthereturned

referencerefertotheobjectintheotherapplicationdomain.(Seerecipe

3.2formoredetailsaboutMBVandMBRtypes.)

Acommontechniquetosimplifythemanagementofapplicationdomains

istouseacontrollerclass.AcontrollerclassisacustomMBRtype.You

createanapplicationdomainandtheninstantiateyourcontrollerclassin

theapplicationdomainusingCreateInstance.Thecontrollerclass

implementsthefunctionalityrequiredbyyourapplicationtomanipulate

theapplicationdomainanditscontents.Thiscouldincludetheloadingof

assemblies,creatingfurtherapplicationdomains,cleaninguppriortothe

deletionoftheapplicationdomain,orenumeratingprogramelements

(somethingyoucan'tnormallydofromoutsideanapplicationdomain).

Thefollowingexampledemonstratestheuseofasimplifiedcontroller

classnamedPluginManager.Wheninstantiatedinanapplicationdomain,

PluginManagerallowsyoutoinstantiateclassesthatimplementthe

IPlugininterface,startandstopthoseplug-ins,andreturnalistof

currentlyloadedplug-ins.

usingSystem;

usingSystem.Reflection;

usingSystem.Collections;

usingSystem.Collections.Specialized;

//Acommoninterfacethatallplug-insmustimplement.

publicinterfaceIPlugin{

voidStart();



voidStop();

}



//AsimpleIPluginimplementationtodemonstratethePluginMan

//controllerclass.

publicclassSimplePlugin:IPlugin{



publicvoidStart(){

Console.WriteLine(AppDomain.CurrentDomain.FriendlyName

":SimplePluginstarting...");

}



publicvoidStop(){

Console.WriteLine(AppDomain.CurrentDomain.FriendlyName

":SimplePluginstopping...");

}

}



//Thecontrollerclass,whichmanagestheloadingandmanipula

//ofplug-insinitsapplicationdomain.

publicclassPluginManager:MarshalByRefObject{



//AListDictionarytoholdkeyedreferencestoIPluginins

privateListDictionaryplugins=newListDictionary();

//Defaultconstructor.

publicPluginManager(){}



//Constructorthatloadsasetofspecifiedplug-insoncr

publicPluginManager(ListDictionarypluginList){

//Loadeachofthespecifiedplug-ins.

foreach(stringplugininpluginList.Keys){



this.LoadPlugin((string)pluginList[plugin],plugin)

}

}



//Loadthespecifiedassemblyandinstantiatethespecifie

//IPluginimplementationfromthatassembly.

publicboolLoadPlugin(stringassemblyName,stringpluginNa

try{

//Loadthenamedprivateassembly.

Assemblyassembly=Assembly.Load(assemblyName);



//CreatetheIPlugininstance,ignorecase.

IPluginplugin=

(IPlugin)assembly.CreateInstance(pluginName,tr

if(plugin!=null){

//AddnewIPlugintoListDictionary

plugins[pluginName]=plugin;

returntrue;

}else{

returnfalse;

}

}catch{

returnfalse;

}

}

publicvoidStartPlugin(stringplugin){



//ExtracttheIPluginfromtheListDictionaryandcall

((IPlugin)plugins[plugin]).Start();

}

publicvoidStopPlugin(stringplugin){



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

4 Create a Type That Can't Cross Application Domain Boundaries

Tải bản đầy đủ ngay(0 tr)

×