Tải bản đầy đủ - 0 (trang)
10 Expose a .NET Component Through COM

10 Expose a .NET Component Through COM

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

Itisrecommendedthatyoudon'tcreateinheritancerelationships

betweenclasses,becausetheserelationshipswillnotbevisible

toCOMclients(although.NETwillattempttosimulateitby

declaringasharedbaseclassinterface).

Itisrecommendedthattheclassesyouareexposingimplement

aninterface.Foraddedversioningcontrol,youcanusethe

attributeSystem.Runtime.InteropServices.GuidAttributetospecify

theGUIDthatshouldbeassignedtoaninterface.

Ideally,youshouldgivethemanagedassemblyastrongnameso

thatitcanbeinstalledintotheGACandsharedamongmultiple

clients.

InorderforaCOMclienttocreatethe.NETobject,itrequiresatype

library(a.tlbfile).Thetypelibrarycanbegeneratedfromanassembly

usingtheTlbexp.execommand-lineutility.Here'sanexampleofthe

syntaxyouuse:

tlbexpManagedLibrary.dll

Onceyougeneratethetypelibrary,youcanreferenceitfromthe

unmanageddevelopmenttool.WithVisualBasic6,youreferencethe.tlb

filefromtheProject/Referencesdialog.InVisualC++6,youcanusethe

#importstatementtoimportthetypedefinitionsfromthetypelibrary.



Chapter16:CommonlyUsedInterfacesand

Patterns

Therecipesinthischaptershowyouhowtoimplementpatternsyouwill

usefrequentlyduringthedevelopmentofMicrosoft.NETFramework

applications.Someofthesepatternsareformalizedusinginterfaces

definedinthe.NETFrameworkclasslibrary.Othersarelessrigid,butstill

requireyoutotakespecificapproachestothedesignandimplementation

ofyourtypes.Therecipesinthischapterdescribehowto

Createserializabletypesthatyoucaneasilystoretodisk,send

acrossthenetwork,orpassbyvalueacrossapplicationdomain

boundaries(recipe16.1).

Provideamechanismthatcreatesaccurateandcompletecopies

(clones)ofobjects(recipe16.2).

Implementtypesthatareeasytocompareandsort(recipe16.3).

Supporttheenumerationoftheelementscontainedincustom

collections(recipe16.4).

Ensurethatatypethatusesunmanagedresourcescorrectly

releasesthoseresourceswhentheyarenolongerneeded

(recipe16.5).

Displaystringrepresentationsofobjectsthatvarybasedon

formatspecifiers(recipe16.6).

Correctlyimplementcustomexceptionandeventargument

types,whichyouwillusefrequentlyinthedevelopmentofyour

applications(recipes16.7and16.8).

ImplementthecommonlyusedSingletonandObserverdesign

patternsusingthebuilt-infeaturesofC#andthe.NET

Frameworkclasslibrary(recipes16.9and16.10).



16.1ImplementaSerializableType

Problem

Youneedtoimplementacustomtypethatisserializable,allowingyouto

Storeinstancesofthetypetopersistentstorage(forexample,a

fileoradatabase).

Transmitinstancesofthetypeacrossanetwork.

Passinstancesofthetype"byvalue"acrossapplicationdomain

boundaries.



Solution

Forserializationofsimpletypes,applytheattribute

System.SerializableAttributetothetypedeclaration.Fortypesthatare

morecomplex,ortocontrolthecontentandstructureoftheserialized

data,implementtheinterfaceSystem.Runtime.Serialization.ISerializable.



Discussion

Recipe2.12showedhowtoserializeanddeserializeanobjectusingthe

formatterclassesprovidedwiththe.NETFrameworkclasslibrary.

However,typesaren'tserializablebydefault.Toimplementacustomtype

thatisserializable,youmustapplytheattributeSerializableAttributeto

yourtypedeclaration.Aslongasallofthedatafieldsinyourtypeare

serializabletypes,applyingSerializableAttributeisallyouneedtodoto

makeyourcustomtypeserializable.Ifyouareimplementingacustom

classthatderivesfromabaseclass,thebaseclassmustalsobe

serializable.

Eachformatterclasscontainsthelogicnecessarytoserializetypes

decoratedwithSerializableAttributeandwillcorrectlyserializeallpublic,

protected,andprivatefields.Thiscodeexcerptshowsthetypeandfield



declarationsofaserializableclassnamedEmployee.

usingSystem;

[Serializable]

publicclassEmployee{

privatestringname;

privateintage;

privatestringaddress;

§

}

Note Classesthatderivefromaserializabletypedon'tinheritthe

attributeSerializableAttribute.Tomakederivedtypes

serializable,youmustexplicitlydeclarethemasserializableby

applyingtheSerializableAttributeattribute.

Youcanexcludespecificfieldsfromserializationbyapplyingtheattribute

System.NonSerializedAttributetothosefields.Asarule,youshould

excludethefollowingfieldsfromserialization:

Fieldsthatcontainnonserializabledatatypes

Fieldsthatcontainvaluesthatmightbeinvalidwhentheobjectis

deserialized,forexample,databaseconnections,memory

addresses,threadIDs,andunmanagedresourcehandles

Fieldsthatcontainsensitiveorsecretinformation,forexample,

passwords,encryptionkeys,andthepersonaldetailsofpeople

andorganizations

Fieldsthatcontaindatathatiseasilyre-creatableorretrievable

fromothersources—especiallyifthedataislarge

Ifyouexcludefieldsfromserialization,youmustimplementyourtypeto

compensateforthefactthatsomedatawon'tbepresentwhenanobject

isdeserialized.Unfortunately,youcan'tcreateorretrievethemissing

datafieldsinaninstanceconstructorbecauseformattersdon'tcall



constructorsduringtheprocessofdeserializingobjects.Themost

commonsolutiontothisproblemistoimplementthe"LazyInitialization"

pattern,inwhichyourtypecreatesorretrievesdatathefirsttimeit's

needed.

ThefollowingcodeshowsamodifiedversionoftheEmployeeclasswith

NonSerializedAttributeappliedtotheaddressfield,meaningthata

formatterwon'tserializethevalueofthisconfidentialfield.TheEmployee

classimplementspublicpropertiestogiveaccesstoeachoftheprivate

datamembers,providingaconvenientplaceinwhichtoimplementlazy

initializationoftheaddressfield.

usingSystem;

[Serializable]

publicclassEmployee{

privatestringname;

privateintage;

[NonSerialized]

privatestringaddress;

//SimpleEmployeeconstructor

publicEmployee(stringname,intage,stringaddress){



this.name=name;

this.age=age;

this.address=address;

}

//Publicpropertytoprovideaccesstoemployee'sname

publicstringName{

get{returnname;}

set{name=value;}

}

//Publicpropertytoprovideaccesstoemployee'sage



publicintAge{

get{returnage;}

set{age=value;}

}



//Publicpropertytoprovideaccesstoemployee'saddress.

//Useslazyinitializationtoestablishaddressbecause

//adeserializedobjectwillnothaveanaddressvalue.

publicstringAddress{

get{

if(address==null){

//Loadtheaddressfrompersistentstorage

;<$VE>

}

returnaddress;

}



set{

address=value;

}

}

}

Forthemajorityofcustomtypes,useoftheattributes

SerializableAttributeandNonSerializedAttributewillbesufficienttomeet

yourserializationneeds.Ifyourequiremorecontrolovertheserialization

process,youcanimplementtheinterfaceISerializable.Theformatter

classesusedifferentlogicwhenserializinganddeserializinginstancesof

typesthatimplementISerializable.ToimplementISerializablecorrectly

youmust

DeclarethatyourtypeimplementsISerializable.

ApplytheattributeSerializableAttributetoyourtypedeclaration

asjustdescribed;donotuseNonSerializedAttributebecauseit

willhavenoeffect.

ImplementtheISerializable.GetObjectDatamethod(usedduring



serialization),whichtakesthefollowingargumenttypes:

System.Runtime.Serialization.SerializationInfo

System.Runtime.Serialization.StreamingContext

Implementanonpublicconstructor(usedduringdeserialization)

thatacceptsthesameargumentsastheGetObjectDatamethod.

Remember,ifyouplantoderiveclassesfromyourserializable

class,maketheconstructorprotected.

Ifcreatingaserializableclassfromabaseclassthatalso

implementsISerializable,yourtype'sGetObjectDatamethodand

deserializationconstructormustcalltheequivalentmethodand

constructorintheparentclass.

Duringserialization,theformattercallstheGetObjectDatamethodand

passesitSerializationInfoandStreamingContextreferencesas

arguments.YourtypemustpopulatetheSerializationInfoobjectwiththe

datayouwanttoserialize.TheSerializationInfoclassprovidesthe

AddValuemethodthatyouusetoaddeachdataitem.Witheachcallto

AddValue,youmustspecifyanameforthedataitem—youusethis

nameduringdeserializationtoretrieveeachdataitem.TheAddValue

methodhas16overloadsthatallowyoutoadddifferentdatatypestothe

SerializationInfoobject.

TheStreamingContextobjectprovidesinformationaboutthepurposeand

destinationoftheserializeddata,allowingyoutochoosewhichdatato

serialize.Forexample,youmightbehappytoserializesecretdataifit's

destinedforanotherapplicationdomaininthesameprocess,butnotif

thedatawillbewrittentoafile.

Whenaformatterdeserializesaninstanceofyourtype,itcallsthe

deserializationconstructor,againpassingaSerializationInfoanda

StreamingContextreferenceasarguments.Yourtypemustextractthe

serializeddatafromtheSerializationInfoobjectusingoneofthe

SerializationInfo.Get*methods,forexample,GetString,GetInt32,or

GetBoolean.Duringdeserialization,theStreamingContextobject

providesinformationaboutthesourceoftheserializeddata,allowingyou



tomirrorthelogicyouimplementedforserialization.

Note Duringstandardserializationoperations,theformattersdon't

usethecapabilitiesoftheStreamingContextobjecttoprovide

specificsaboutthesource,destination,andpurposeof

serializeddata.However,ifyouwishtoperformcustomized

serialization,yourcodecanconfiguretheformatter's

StreamingContextobjectpriortoinitiatingserializationand

deserialization.Consultthe.NETFrameworkSDK

documentationfordetailsoftheStreamingContextclass.

ThisexampleshowsamodifiedversionoftheEmployeeclassthat

implementstheISerializableinterface.Inthisversion,theEmployee

classdoesn'tserializetheaddressfieldiftheprovidedStreamingContext

objectspecifiesthatthedestinationoftheserializeddataisafile.Thefull

codeforthisexampleiscontainedinthefileSerializableExample.csin

thesamplecodeforthischapter.TheSerializableExample.csfilealso

includesaMainmethodthatdemonstratestheserializationand

deserializationofanEmployeeobject.

usingSystem;

usingSystem.Runtime.Serialization;

[Serializable]

publicclassEmployee:ISerializable{

privatestringname;

privateintage;

privatestringaddress;



//SimpleEmployeeconstructor

publicEmployee(stringname,intage,stringaddress){



this.name=name;

this.age=age;

this.address=address;

}



//Constructorrequiredtoenableaformattertodeserializ

//Employeeobject.Youshoulddeclaretheconstructorpriv

//leastprotectedtoensureitisnotcalledunnecessarily

privateEmployee(SerializationInfoinfo,StreamingContextc



//ExtractthenameandageoftheEmployee,whichwill

//presentintheserializeddataregardlessoftheval

//StreamingContext

name=info.GetString("Name");

age=info.GetInt32("Age");



//AttempttoextracttheEmployee'saddressandfailg

//ifitisnotavailable

try{

address=info.GetString("Address");

}catch(SerializationException){

address=null;

}

}

//Name,Age,andAddresspropertiesnotshown

§



//DeclaredbytheISerializableinterface,theGetObjectDa

//providesthemechanismwithwhichaformatterobtainsth

//datathatitshouldserialize

publicvoidGetObjectData(SerializationInfoinf,StreamingC



//AlwaysserializetheEmployee'snameandage.

inf.AddValue("Name",name);

inf.AddValue("Age",age);



//Don'tserializetheEmployee'saddressiftheStream

//indicatesthattheserializeddataistobewritten

if((con.State&StreamingContextStates.File)==0){

inf.AddValue("Address",address);



}

}

}



16.2ImplementaCloneableType

Problem

Youneedtocreateacustomtypethatprovidesasimplemechanismfor

programmerstocreatecopiesoftypeinstances.



Solution

ImplementtheSystem.ICloneableinterface.



Discussion

Whenyouassignonevaluetypetoanother,youcreateacopyofthe

value.There'snolinkbetweenthetwovalues—achangetoonewon't

affecttheother.However,whenyouassignonereferencetypetoanother

(excludingstrings,whichreceivespecialtreatmentbytheruntime),you

don'tcreateanewcopyofthereferencetype.Instead,bothreference

typesrefertothesameobject,andchangestothevalueoftheobjectare

reflectedinbothreferences.Tocreateatruecopyofareferencetype,

youmustclonetheobjecttowhichitrefers.

TheICloneableinterfaceidentifiesatypeascloneableanddeclaresthe

Clonemethodasthemechanismthroughwhichyouobtainacloneofan

object.TheClonemethodtakesnoargumentsandreturnsa

System.Object,regardlessoftheimplementingtype.Thismeansthat

onceyoucloneanobject,youmustexplicitlycasttheclonetothecorrect

type.

TheapproachyoutaketoimplementingtheClonemethodforacustom

typedependsonthedatamembersdeclaredwithinthetype.Ifthe

customtypecontainsonlyvalue-type(int,byte,andsoon)and

System.Stringdatamembers,youcanimplementtheClonemethodby

instantiatinganewobjectandsettingitsdatamemberstothesame

valuesasthecurrentobject.TheObjectclass(fromwhichalltypes

derive)includestheprotectedmethodMemberwiseClone,which

automatesthisprocess.Hereisanexamplethatshowsasimpleclass



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

10 Expose a .NET Component Through COM

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

×