Impliciete vertalingen van methodehandtekening in .NET-interop
Om de programmeertaal neutraal te houden, retourneren het Windows COM-systeem en veel Windows-API's een 4 byte integertype genaamd HRESULT
een om aan te geven of een API is geslaagd of mislukt, samen met enkele informatie over de fout. Andere waarden die aan de aanroeper moeten worden doorgegeven, worden 'geretourneerd' via aanwijzerparameters die fungeren als 'out'-parameters en zijn meestal de laatste parameter in de handtekening. Talen zoals C# en Visual Basic vertalen traditioneel een foutcode naar een uitzondering zodat deze overeenkomt met de manier waarop fouten meestal worden doorgegeven in de taal, en verwachten dat handtekeningen van de interop-methode het HRESULT
niet bevatten. Als u de methodehandtekening wilt vertalen naar een systeemeigen handtekening, verplaatst de runtime de retourwaarde van de methode naar een extra 'out'-parameter met een extra indirectieniveau (met andere woorden, wordt deze een aanwijzer naar het retourtype van de beheerde handtekening) en wordt een retourwaarde aangenomen HRESULT
. Als de beheerde methode retourneert void
, wordt er geen extra parameter toegevoegd en wordt de retourwaarde een HRESULT
. Zie bijvoorbeeld de volgende twee C#COM-methoden die worden vertaald naar dezelfde systeemeigen handtekening:
int Add(int a, int b);
void Add(int a, int b, out int sum);
HRESULT Add(int a, int b, /* out */ int* sum);
PreserveSig in COM
Voor alle COM-methoden in C# wordt standaard de vertaalde handtekening gebruikt. Als u methoden wilt gebruiken en exporteren zonder de handtekeningomzetting en -verwerking van HRESULT
waarden, voegt u de PreserveSigAttribute methode toe aan een COM-interfacemethode. Wanneer het kenmerk wordt toegepast op een methode, wordt er geen vertaling naar de handtekening uitgevoerd en worden er geen uitzonderingen gegenereerd voor mislukte HRESULT
waarden. Dit is van toepassing op zowel ingebouwde COM als op bron gegenereerde COM. Zie bijvoorbeeld de volgende C#-methodehandtekening met een PreserveSig
kenmerk en de bijbehorende systeemeigen handtekening.
[PreserveSig]
int Add(int a, int b, out int sum);
HRESULT Add(int a, int b, int* sum);
Dit kan handig zijn als de methode verschillende HRESULT
waarden retourneert die geen fouten zijn, maar anders moet worden verwerkt. Sommige methoden kunnen bijvoorbeeld de waarde S_FALSE
retourneren wanneer een methode niet mislukt, maar alleen gedeeltelijke resultaten retourneert en S_OK
wanneer alle resultaten worden geretourneerd.
PreserveSig
met P/Invokes
Het DllImportAttribute kenmerk heeft ook het bool PreserveSig
veld dat op dezelfde manier werkt als de PreserveSigAttribute
, maar is standaard ingesteld true
op . Als u wilt aangeven dat de runtime de beheerde handtekening moet vertalen en de HRESULT
geretourneerde handtekening moet verwerken, stelt u het PreserveSig
veld in op het DllImportAttribute
veld false
. Zie bijvoorbeeld de volgende handtekeningen van twee P/Invokes naar dezelfde systeemeigen methode, één met PreserveSig
ingesteld op false
en één met de standaardwaarde true
.
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true, PreserveSig = false)]
public static extern void SHAutoComplete(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
[DllImport("shlwapi.dll", EntryPoint = "SHAutoComplete", ExactSpelling = true)]
public static extern int SHAutoCompleteHRESULT(IntPtr hwndEdit, SHAutoCompleteFlags dwFlags);
Notitie
Door de bron gegenereerde P/Invokes, die gebruikmaken van het LibraryImportAttributeveld, hebben geen PreserveSig
veld. Bij de gegenereerde code wordt ervan uitgegaan dat de systeemeigen en beheerde handtekening identiek zijn. Zie brongegenereerde P/Invokes voor meer informatie.
Waarden handmatig verwerken HRESULT
Wanneer u een methode aanroept die een PreserveSig
HRESULT
retourneert, kunt u de ThrowExceptionForHR methode gebruiken om de bijbehorende uitzondering te genereren als de HRESULT
fout aangeeft. Bij het implementeren van een PreserveSig
methode kunt u ook de GetHRForException methode gebruiken om de HRESULT
methode te retourneren die een overeenkomstige waarde voor de uitzondering aangeeft.
Marshal HRESULTs as structs
Wanneer u een PreserveSig
methode gebruikt, int
is dit naar verwachting het beheerde type voor HRESULT
. Met behulp van een aangepaste 4-byte-struct als het retourtype kunt u echter helpermethoden en eigenschappen definiëren die het werken met de HRESULT
. In ingebouwde marshalling werkt dit automatisch. Als u een struct wilt gebruiken in plaats van int
de beheerde weergave van HRESULT
door de bron gegenereerde marshalling, voegt u het MarshalAsAttribute kenmerk toe met Error als het argument. De aanwezigheid van dit kenmerk herinterpreteert de bits van de HRESULT
struct.