Brug af tidlig og sen binding i forbindelse med automatisering

Oversættelser af artikler Oversættelser af artikler
Artikel-id: 245115 - Få vist de produkter, som denne artikel refererer til.
Udvid alle | Skjul alle

På denne side

Sammenfatning

Måden, du binder til en automatiseringsserver på, kan påvirke mange ting i programmet, f.eks. ydeevnen, fleksibiliteten og muligheden for at vedligeholde programmet.

I denne artikel forklares, hvilke bindingstyper der er tilgængelige for automatiseringsklienter, og fordelene og ulemperne ved begge metoder vægtes.

Yderligere Information

Automatisering er en proces, hvor én softwarekomponent kommunikerer med og/eller styrer en anden softwarekomponent ved hjælp af Microsofts COM (Component Object Model). Automatisering er grundlaget for hovedparten af den kommunikation på tværs af komponenter, der benyttes i sprog som Visual Basic eller Visual Basic for Applications, og er blevet en normal del af de fleste programmer.

Hidtil har et automatiseringsobjekt været et objekt, der understøtter IDispatch-grænsefladen. I denne grænseflade kan klienter kalde metoder og egenskaber på kørselstidspunktet uden præcist at skulle vide, hvilket objekt de kommunikerer med på designtidspunktet. Denne proces kaldes for sen binding. Men i dag kan udtrykket automatiseringsobjekt bruges om næsten alle COM-objekter, selv de objekter, der ikke understøtter IDispatch (og derfor ikke kan bindes sent). I denne artikel antages, at det objekt, du vil automatisere, understøtter begge bindingsmetoder.

Hvad er binding?

Binding er en proces, hvor funktionskald, der er skrevet af programmøren, afstemmes med den faktiske kode (intern eller ekstern), som implementerer funktionen. Dette foregår, når programmet kompileres, og alle de funktioner, der kaldes i koden, skal være bundet, inden koden kan køres.

Du kan få en forståelse af processen ved at sammenligne "binding" med det at udgive en bog. Forestil dig, at koden svarer til bogens tekst, hvor du i et bestemt afsnit f.eks. har skrevet "se kapitel 12, side x for at få flere oplysninger". Du kender ikke sidenummeret, før bogen er færdig, så inden bogen kan læses, som den er tiltænkt, skal alle bogens sider være bundet sammen, og det korrekte sideantal skal indsættes i afsnittet. Du venter på, at bogen "bindes sammen", inden du kan henvise til andre dele af bogen.

At binde software er en lignende proces. Koden består af dele, som skal samles, inden koden kan "læses". Binding er, når du erstatter funktionsnavne med hukommelsesadresser (eller hukommelsesforskydninger for at være mere præcis), som er det sted, hvor koden "går til", når funktionen kaldes. I forbindelse med COM-objekter er adressen en hukommelsesforskydning i en tabel bestående af markører (kaldet v-tabellen), der holdes af objektet. Når en COM-funktion bindes, bindes den via v-tabellen.

Et COM-objekts struktur er enkel. Når koden indeholder en reference til et objekt, indeholder den en indirekte markør til toppen af v-tabellen. V-tabellen er en matrix bestående af hukommelsesadresser, hvor de enkelte poster er forskellige funktioner, der kan kaldes på det pågældende objekt. Hvis du vil kalde den tredje funktion på et COM-objekt, går du tre poster ned i tabellen og går derefter til den hukommelsesplacering, som er angivet der. Derved køres koden for funktionen, og når koden er kørt, vender du tilbage og er klar til at køre den næste kodelinje.

+-[Code]------------+  +.................................[COM Object]...+
|                   |  : +-------------+                                :
|Set obj = Nothing -|--->| obj pointer |                                :
|                   |  : +-|-----------+                                :
+-------------------+  :   |   +-----------------+                      :
                       :   +-->| v-table pointer |                      :
                       :       +--|--------------+                      :
                       :          |                                     :
                       :          |  +----------------------------+     :
                       :  (3rd)   |  | Function 1 Address pointer |     :
                       : (Offset) |  +----------------------------+     :
                       :          |  | Function 2 Address pointer |     :
                       :          |  +----------------------------+     :
                       :          +->| Function 3 Address pointer |     :
                       :             +----------------------------+     :
                       +................................................+

				
I eksemplet ovenfor vises, hvad der sker, når et COM-objekt frigives. Da alle COM-objekter nedarver fra IUnknown, er de første tre poster i tabellen metoderne til IUnknown. Når du skal frigøre et objekt, kalder koden den tredje funktion i v-tabellen (IUnknown::Release).

Heldigvis udføres dette arbejde af Visual Basic i baggrunden. Som Visual Basic-programmør skal du aldrig arbejde direkte med en v-tabel. Men denne struktur er gældende for binding af alle COM-objekter, og det er vigtigt, at du er bekendt med den for at kunne forstå, hvad binding er.

Tidlig binding

Eksemplet ovenfor er det, der kaldes for tidlig (eller v-tabel) binding. For alle COM-objekter sker denne form for binding, hver gang et COM-objekts IUnknown-grænseflade kaldes. Men hvad med objektets andre funktioner? Hvordan kalder du objektets opdateringsmetode eller dets overordnede egenskab? Disse funktioner er brugerdefinerede og er normalt entydige for et objekt. Hvis det ikke er muligt at antage deres placeringer i v-tabellen, hvordan finder du så de funktionsadresser, der er nødvendige for at kalde dem?

Svaret afhænger naturligvis af, om du på forhånd ved, hvordan objektets v-tabel ser ud. Hvis du gør det, kan du foretage den samme tidlige bindingsproces på objektets brugerdefinerede metoder, som du gjorde i forbindelse med dets IUnknown-metoder. Det er dette, der generelt forstås ved "tidlig binding".

Hvis du vil anvende tidlig binding på et objekt, skal du vide, hvordan dets v-tabel ser ud. I Visual Basic kan du gøre dette ved at føje en reference til et typebibliotek, som beskriver objektet, dets grænseflade (v-tabel) og alle de funktioner, der kan kaldes på objektet. Når du har gjort dette, kan du angive, at et objekt er af en bestemt type og derefter indstille og bruge det pågældende objekt ved hjælp af v-tabellen. Hvis du f.eks. vil automatisere Microsoft Office Excel ved hjælp af tidlig binding, skal du føje en reference til "Microsoft Excel 8.0-objektbiblioteket" fra dialogboksen Projekt|Referencer og derefter angive, at variablen er af typen "Excel.Application". Herefter vil alle opkald til objektvariablen blive bundet tidligt:
' Set reference to 'Microsoft Excel 8.0 Object Library' in
' the Project|References dialog (or Tools|References for VB4 or VBA).

' Declare the object as an early-bound object
  Dim oExcel As Excel.Application

  Set oExcel = CreateObject("Excel.Application")

' The Visible property is called via the v-table
  oExcel.Visible = True
				
Denne metode fungerer godt det meste af tiden, men hvad sker der, hvis du ikke præcist ved, hvilket objekt du skal bruge på designtidspunktet? Hvad hvis du f.eks. har behov for at kommunikere med flere versioner af Excel eller eventuelt med et "ukendt" objekt?

Sen binding

COM indeholder IDispatch. Objekter, der implementerer IDispatch, siges at have en brugergrænseflade til dispenser (hvis det er den eneste grænseflade, de understøtter) eller en dobbeltgrænseflade (hvis de også har en brugerdefineret grænseflade, du kan foretage tidlig binding til). Klienter, der bindes til IDispatch, siges at være "sent bundet", fordi den præcise egenskab eller metode, de kalder, bestemmes på kørselstidspunktet ved at benytte IDispatch-metoderne til at finde dem. Hvis vi går tilbage til bogeksemplet tidligere, skal du forestille dig, at det er ligesom en fodnote, der dirigerer dig til indholdsfortegnelsen, hvor du skal slå sidenummeret op på "læsetidspunktet" i stedet for, at det allerede er angivet i teksten.

Grænsefladens magi styres af to funktioner: GetIDsOfNames og Invoke. Den første knytter funktionsnavne (strenge) til et id (kaldet et dispid), der repræsenterer funktionen. Når du kender id'et til den funktion, du vil kalde, kan du kalde den ved hjælp af Invoke-funktionen. Denne form for metodeaktivering kaldes for "sen binding".

På samme måde bruger du objektangivelsen i Visual Basic til at angive, hvordan objektet skal bindes. Hvis du angiver en objektvariabel til "Objekt", fortæller du faktisk Visual Basic, at IDispatch skal benyttes, og der er derfor tale om sen binding:
' No reference to a type library is needed to use late binding.
' As long as the object supports IDispatch, the method can 
' be dynamically located and invoked at run-time.

' Declare the object as a late-bound object
  Dim oExcel As Object

  Set oExcel = CreateObject("Excel.Application")

' The Visible property is called via IDispatch
  oExcel.Visible = True
				
Som du kan se, er resten af koden den samme. Den eneste forskel mellem tidlig binding og sen binding (hvad angår den kode, du skriver) findes i variabelangivelsen.

Det er vigtigt at bemærke, at det er den kaldte funktion, der "bindes sent", og ikke den måde, funktionen kaldes på. Fra den tidligere generelle diskussion om binding ved du, at selve IDispatch er "tidligt bundet:" det vil sige, at Visual Basic foretager kaldet for at angive egenskaben Visible via en v-tabelpost (IDispatch::Invoke) på samme måde som ved et COM-kald. Selve COM-objektet er ansvarligt for at videresende kaldet til den korrekte funktion, så Excel kan vises. Dette kneb gør det muligt for Visual Basic-klienten at blive kompileret (dvs. bundet til en gyldig funktionsadresse), men stadig ikke præcist vide, hvilken funktion der faktisk vil gøre arbejdet.

Dispid-binding

Nogle automatiseringsklienter (især MFC og Visual Basic 3.0, men også Visual Basic 5.0 og 6.0 med hensyn til ActiveX-objekter) benytter en hybrid form for sen binding, der kaldes dispid-binding. Hvis COM-objektet er kendt på designtidspunktet, kan dispid'erne for de kaldte funktioner cachelagres og videresendes direkte til IDispatch::Invoke, uden at det er nødvendigt at kalde GetIDsOfNames på kørselstidspunktet. Dette kan forbedre ydeevnen meget, da der kun foretages ét COM-kald pr. funktion i stedet for to.

Dispid-binding er ikke en mulighed, du normalt kan vælge i Visual Basic 5.0 eller 6.0. Den bruges i forbindelse med objekter, der refereres til i et typebibliotek, men som ikke indeholder en brugerdefineret grænseflade (dvs. objekter, der kun har en brugergrænseflade til dispenser), og i forbindelse med ActiveX-objekter, men i Visual Basic benyttes der generelt tidlig binding de steder, hvor du normalt ville benytte dispid-binding.

Hvilken form for binding skal du benytte?

Svaret på dette spørgsmål afhænger lige så meget af projektets udformning som af alle andre ting. Microsoft anbefaler tidlig binding i næsten alle tilfælde. Men der kan være grunde til at vælge sen binding.

Tidlig binding er den foretrukne metode. Den giver de bedste resultater, fordi programmet binder direkte til adressen på den kaldte funktion, og der skal ikke bruges ekstra tid på foretage en søgning på kørselstidspunktet. Hvad angår den samlede kørselshastighed er metoden mindst dobbelt så hurtig som sen binding.

Tidlig binding leverer også typesikkerhed. Når en reference angives til komponentens typebibliotek, understøttes IntelliSense i Visual Basic, hvilket hjælper dig med at kode hver enkelt funktion korrekt. Visual Basic advarer dig også, hvis datatypen for en parameter eller returværdi er forkert, hvilket sparer dig for en masse tid i forbindelse med skrivning og fejlfinding af kode.

Sen binding er stadig nyttig i situationer, hvor et objekts præcise grænseflade ikke kendes på designtidspunktet. Hvis programmet prøver at kommunikere med flere ukendte servere eller skal aktivere funktioner efter navn (f.eks. ved hjælp af funktionen CallByName i Visual Basic 6.0), skal du benytte sen binding. Sen binding er også nyttig, hvis du vil løse problemer med kompatibiliteten mellem flere versioner af en komponent, eller hvis grænsefladen er blevet ændret eller tilpasset forkert mellem diverse versioner.

Fordelene ved tidlig binding gør denne metode til det bedste valg, når det er muligt.

Bevarelse af kompatibilitet mellem flere versioner

Hvis du benytter en komponent, der ikke videredistribueres med installationspakken, og ikke ved præcist, hvilken version der kommunikeres med på kørselstidspunktet, skal du være ekstra opmærksom på at foretage tidlig binding til en grænseflade, der er kompatibel med alle versioner af komponenten, eller (i nogle tilfælde) benytte sen binding til at kalde en metode, der muligvis findes i en bestemt version. Hvis den pågældende metode ikke findes i den version, der er installeret på klientsystemet, vil den sene binding mislykkes.

Microsoft Office-programmer er et godt eksempel på sådanne COM-servere. I Office-programmer udvides grænsefladerne normalt, så det er muligt at tilføje nye funktioner eller afhjælpe tidligere problemer mellem versioner. Hvis du har behov for at automatisere et Office-program, anbefales det, at du foretager tidlig binding til den ældste version af det produkt, du forventer, vil blive installeret på klientens system. Hvis du f.eks. skal kunne automatisere Excel 95, Excel 97, Excel 2000 og Excel 2002, skal du benytte typebiblioteket til Excel 95 (XL5en32.olb) for at bevare kompatibilitet mellem alle tre versioner.

Office-programmer demonstrerer også, at objektmodeller med store dobbeltgrænseflader kan have begrænsninger i forbindelse med marshalling på nogle platforme. Brug IDispatch, hvis koden skal kunne fungere bedst muligt på tværs af alle platforme. Du kan finde flere oplysninger om bevarelse af kompatibilitet, når du arbejder med Office-programmer, ved at klikke på følgende artikelnummer for at få vist artiklen i Microsoft Knowledge Base:
247579 Brug DISPID-binding til automatisering af Office-programmer, når det er muligt. Artiklen er evt. på engelsk.

Referencer

Du kan finde flere oplysninger om COM, v-tabeller og brug af automatisering i følgende bøger:
Rogerson, Dale, Inside COM, MSPRESS, ISBN: 1-57231-349-8.

Curland, Matt, Advanced Visual Basic 6, DevelopMentor, 0201707128.

Egenskaber

Artikel-id: 245115 - Seneste redigering: 23. november 2007 - Redigering: 7.1
Oplysningerne i denne artikel gælder:
  • Microsoft Office Ultimate 2007
  • Microsoft Office Enterprise 2007
  • Microsoft Office Professional 2007
  • Microsoft Office Professional Plus 2007
  • Microsoft Office Standard 2007
  • Microsoft Office Home and Student 2007
  • Microsoft Office Basic 2007
  • Microsoft Office Standard Edition 2003
  • Microsoft Office XP Developer Edition
  • Microsoft Office 2000 Developer Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic 6.0 Enterprise Edition
Nøgleord: 
kbinfo kbautomation KB245115

Send feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com