Använda tidig och sen bindning i Automation

Artikelöversättning Artikelöversättning
Artikel-id: 245115 - Visa produkter som artikeln gäller.
Visa alla | Dölj alla

På den här sidan

Sammanfattning

Hur du binder en Automation-server kan påverka många saker i programmet, till exempel prestanda, flexibilitet och underhållsbarhet.

I den här artikeln beskrivs olika typer av bindning som är tillgängliga för Automation-klienter samt för- och nackdelar med respektive metod.

Mer Information

Automation är en process där en programkomponent kommunicerar med och/eller styr en annan programkomponent med hjälp av Microsofts COM-modell (Component Object Model). Automation ligger till grund för den mesta kommunikationen mellan olika komponenter i språk som Visual Basic eller Visual Basic for Applications och har blivit ett normalt inslag i de flesta program.

Historiskt är ett Automation-objekt ett objekt som stöder IDispatch-gränssnittet. Detta gränssnitt gör det möjligt för klienter att anropa metoder och egenskaper vid körningstillfället utan att de måste veta exakt vilket objekt de kommunicerar med vid designtillfället, en process som kallas sen bindning. I dag kan emellertid termen Automation-objekt användas om nästan vilket COM-objekt som helst, även sådana som inte stöder IDispatch (och därför inte kan vara sent bundna). I den här artikeln förutsätts att ditt Automation-objekt stöder båda bindningsmetoderna.

Vad är bindning?

Bindning är en matchning av funktionsanrop som skrivits av programmeraren mot den faktiska koden (intern eller extern) som implementerar funktionen. Bindning sker när programmet kompileras, och alla funktioner som anropas i kod måste bindas innan koden kan köras.

För att förstå processen kan du tänka dig "bindning" som en företeelse vid publicering av en bok. Tänk dig att din kod är som texten i en bok där du har skrivit ungefär "se kapitel 12 på sidan x för mer information". Du vet inte vilket sidnumret blir förrän boken är klar. Innan stycket kan läsas som det är avsett måste bokens alla sidor bindas samman och rätt sidnummer infogas i stycket. Du väntar på att boken ska "bindas" innan du kan hänvisa till andra delar av den.

Det är ungefär samma sak att binda program. Din kod består av delar som måste sammanställas innan koden kan "läsas". Bindning innebär att funktionsnamn ersätts av minnesadresser (eller rättare sagt minnesförskjutningar) som koden "hoppar till" när funktionen anropas. För COM-objekt är adressen en minnesförskjutning i en tabell med pekare (kallad v-tabellen) som innehas av objektet. När en COM-funktion är bunden är den bunden genom v-tabellen.

COM-objekt har en mycket enkel struktur. När koden innehåller en referens till ett objekt innehåller den en indirekt pekare till v-tabellens översta del. V-tabellen är en matris med minnesadresser, där varje post är en separat funktion som kan anropas på detta objekt. För att anropa den tredje funktionen på ett COM-objekt hoppar du tre poster nedåt i tabellen och sedan till minnesplatsen som anges där. Därmed körs koden för funktionen, och när detta är klart kommer du tillbaka och är klar att köra nästa kodrad.

+-[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 |     :
                       :             +----------------------------+     :
                       +................................................+

				
Exemplet ovan visar vad som händer när ett COM-objekt frigörs. Eftersom alla COM-objekt ärver från IUnknown är de första tre posterna i tabellerna metoderna för IUnknown. När du behöver frigöra ett objekt anropar koden den tredje funktionen i v-tabellen (IUnknown::Release).

Som tur är görs detta i bakgrunden av Visual Basic. Som Visual Basic-programmerare behöver du aldrig hantera en v-tabell direkt. Alla COM-objekt binds emellertid enligt denna struktur, och det är därför viktigt att du känner till den för att förstå vad bindning är.

Tidig bindning

Ovanstående är ett exempel på så kallad tidig bindning (eller v-tabellbindning). För alla COM-objekt sker denna form av bindning så snart ett COM-objekts IUnknown-gränssnitt anropas. Men hur förhåller det sig med objektets övriga funktioner? Hur anropar man dess Refresh-metod eller Parent-egenskap? Detta är anpassade funktioner som normalt är unika för ett objekt. Om det inte är möjligt att dra några slutsatser om deras platser i v-tabellen, hur hittar man då funktionsadresserna som krävs för att anropa dem?

Svaret beror givetvis på om du känner till objektets v-tabell i förväg. Om du känner till den kan du genomföra samma tidiga bindningsprocess till objektets anpassade metoder som du gjorde till dess IUnknown-metoder. Detta kallas i allmänhet "tidig bindning".

För att kunna använda tidig bindning på ett objekt måste du veta hur dess v-tabell ser ut. I Visual Basic kan du göra detta genom att lägga till en referens till ett typbibliotek som beskriver objektet, dess gränssnitt (v-tabell) och alla funktioner som kan anropas på objektet. När detta är gjort kan du deklarera ett objekt som tillhörande en viss typ och sedan ange och använda objektet med hjälp av v-tabellen. Om du till exempel vill automatisera Microsoft Office Excel med hjälp av tidig bindning kan du lägga till en referens till "Microsoft Excel 8.0 Object Library" från dialogrutan Project|References och sedan deklarera variabeln som tillhörande typen "Excel.Application". Därefter är alla anrop till objektvariabeln tidigt bundna:
' 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
				
Den här metoden fungerar utmärkt i de flesta fall, men vad gör man om man inte känner till exakt vilket objekt som kommer att användas vid designtillfället? Vad gör man till exempel om man behöver kommunicera med flera versioner av Excel, eller kanske med ett helt "okänt" objekt?

Sen bindning

I COM ingår IDispatch. Objekt som implementerar IDispatch sägs ha ett disp-gränssnitt (om det är det enda gränssnitt de stöder) eller ett dubbelt gränssnitt (om de även har ett anpassat gränssnitt som det går att binda tidigt till). Klienter som binder till IDispatch sägs vara "sent bundna" eftersom den exakta egenskap eller metod de anropar fastställs vid körningstillfället med hjälp av IDispatch. Om vi återgår till bokexemplet tidigare kan vi tänka på det som en fotnot som leder till innehållsförteckningen, där sidnumret måste "letas upp" vid "läsningstillfället" och inte redan är tryckt i texten.

Gränssnittets magi styrs av två funktioner: GetIDsOfNames och Invoke. Den första mappar funktionsnamn (strängar) till en identifierare (en så kallad dispid) som representerar funktionen. När du känner till ID:t för funktionen du vill anropa kan du anropa den med hjälp av Invoke-funktionen. Den här formen av metodanrop kallas "sen bindning".

I Visual Basic styr din objektdeklaration hur du anger objektets bindning. Om du deklarerar en objektvariabel som "Object" anger du i själva verket att IDispatch och därmed sen bindning ska användas:
' 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 är resten av koden oförändrad. Den enda skillnaden mellan tidig och sen bindning (vad gäller koden du skriver) ligger i variabeldeklarationen.

Lägg märke till att det som är "sent bundet" är funktionen som anropas och inte sättet den anropas på. Från den tidigare diskussionen av bindning i allmänhet bör du lägga märke till att IDispatch i sig är "tidigt bundet": detta betyder att Visual Basic gör anropet för att ange Visible-egenskapen genom en v-tabellpost (IDispatch::Invoke) på samma sätt som för alla COM-anrop. COM-objektet själv ansvarar för att anropet vidarebefordras till rätt funktion så att Excel blir synligt. Denna indirekthet gör att Visual Basic-klienten kan kompileras (det vill säga bindas till en giltig funktionsadress) utan att det är känt exakt vilken funktion som gör jobbet.

Dispid-bindning

I vissa Automation-klienter (mest märkbart MFC och Visual Basic 3.0, men även Visual Basic 5.0 och 6.0 med avseende på ActiveX-kontroller) används en hybridform av sen bindning som kallas dispid-bindning. Om COM-objektet är känt vid designtillfället kan dispiderna för funktionerna som anropas cachelagras och överföras direkt till IDispatch::Invoke utan att GetIDsOfNames behöver anropas vid körningstillfället. Detta kan öka prestanda i hög grad, eftersom det bara krävs ett COM-anrop per funktion i stället för två.

Dispid-bindning är inte ett alternativ som normalt kan väljas i Visual Basic 5.0 eller 6.0. Det används för objekt som refereras till i ett typbibliotek men inte innehåller ett anpassat gränssnitt (det vill säga för objekt som bara har ett disp-gränssnitt) och för sammansatta ActiveX-kontroller. I Visual Basic används emellertid i allmänhet tidig bindning när dispid-bindning normalt skulle användas.

Vilken form av bindning ska jag använda?

Svaret på den här frågan beror bland annat på projektets design. Microsoft rekommenderar tidig bindning i nästan alla fall, men det kan finnas skäl att välja sen bindning.

Tidig bindning bör utnyttjas i första hand. Det ger bäst prestanda, eftersom programmet binder direkt till adressen till funktionen som anropas, och det uppstår inte någon extra belastning på grund av sökning vid körningstillfället. Mätt i total körningshastighet är tidig bindning minst dubbelt så snabb som sen bindning.

Tidig bindning ger även typsäkerhet. När du har angett en referens till komponentens typbibliotek ger Visual Basic IntelliSense-stöd som hjälper dig att koda varje funktion korrekt. Visual Basic varnar även om datatypen för en parameter eller ett returvärde är felaktig, vilket spar mycket tid vid skrivning och felsökning av kod.

Sen bindning är trots detta användbar i sådana fall där objektets exakta gränssnitt inte är känt vid designtillfället. Om programmet försöker kommunicera med flera okända servrar eller behöver anropa funktioner med namn (exempelvis med hjälp av Visual Basic 6.0-funktionen CallByName) måste du använda sen bindning. Sen bindning är även användbar för att undvika kompatibilitetsproblem mellan flera versioner av en komponent som felaktigt har ändrat eller anpassat sitt gränssnitt mellan versioner.

Fördelarna med tidig bindning gör den till det bästa valet närhelst den kan användas.

Upprätthålla kompatibilitet mellan flera versioner

Om du kommer att använda en komponent som du inte distribuerar med ditt installationspaket, och du inte kan vara säker på exakt vilken version du kommer att kommunicera med vid körningstillfället, bör du bemöda dig om att binda tidigt till ett gränssnitt som är kompatibelt med alla versioner av komponenten. Du kan även (i vissa fall) använda sen bindning för att anropa en metod som kan finnas i en viss version och avslutas kontrollerat om metoden inte finns i versionen som är installerad på kundsystemet.

Microsoft Office-program utgör ett bra exempel på sådana COM-servrar. Office-program expanderar normalt sina gränssnitt för att lägga till nya funktioner eller korrigera tidigare brister mellan versioner. Om du behöver automatisera ett Office-program bör du binda tidigt till den tidigaste version av produkten du förväntar dig kan vara installerad på kundens system. Om du till exempel behöver kunna automatisera Excel 95, Excel 97, Excel 2000 och Excel 2002 ska du använda typbiblioteket för Excel 95 (XL5en32.olb) för att upprätthålla kompatibilitet med samtliga tre versioner.

Office-program visar även att objektmodeller med stora dubbla gränssnitt kan ha vissa begränsningar vid konvertering på vissa plattformar. För att din kod ska fungera så bra som möjligt på alla plattformar ska du använda IDispatch. Om du vill veta mer om hur du upprätthåller kompatibilitet vid arbete med Office-program klickar du på följande artikelnummer och läser artikeln i Microsoft Knowledge Base:
247579 Använda DISPID-bindning för att automatisera Office-program när det är möjligt (Länken kan leda till en webbplats som är helt eller delvis på engelska)

Referenser

Mer information om COM, v-tabeller och användning av Automation finns i följande böcker:
Rogerson, Dale, Inside COM, MSPRESS, ISBN: 1-57231-349-8.

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

Egenskaper

Artikel-id: 245115 - Senaste granskning: den 23 november 2007 - Revision: 7.1
Informationen i denna artikel gäller:
  • 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
Nyckelord: 
kbinfo kbautomation KB245115

Ge 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