Referentieassembly's
Referentieassembly's zijn een speciaal type assembly dat alleen de minimale hoeveelheid metagegevens bevat die nodig zijn om het openbare API-oppervlak van de bibliotheek weer te geven. Ze bevatten declaraties voor alle leden die significant zijn bij het verwijzen naar een assembly in buildhulpprogramma's, maar sluit alle ledenimplementaties en declaraties van privéleden uit die geen waarneembare invloed hebben op hun API-contract. Normale assembly's worden daarentegen implementatieassembly's genoemd.
Referentieassembly's kunnen niet worden geladen voor uitvoering, maar ze kunnen op dezelfde manier worden doorgegeven als compilerinvoer als implementatieassembly's. Referentieassembly's worden meestal gedistribueerd met de Software Development Kit (SDK) van een bepaald platform of een bepaalde bibliotheek.
Met behulp van een referentieassembly kunnen ontwikkelaars programma's bouwen die gericht zijn op een specifieke bibliotheekversie zonder dat ze de volledige implementatieassembly voor die versie hebben. Stel dat u alleen de nieuwste versie van een bibliotheek op uw computer hebt, maar u een programma wilt bouwen dat is gericht op een eerdere versie van die bibliotheek. Als u rechtstreeks compileert op basis van de implementatieassembly, kunt u per ongeluk API-leden gebruiken die niet beschikbaar zijn in de eerdere versie. U vindt deze fout alleen bij het testen van het programma op de doelcomputer. Als u compileert op basis van de referentieassembly voor de eerdere versie, krijgt u onmiddellijk een compilatiefout.
Een referentieassembly kan ook een contract vertegenwoordigen, dat wil zeggen een set API's die niet overeenkomen met de concrete implementatieassembly. Dergelijke referentieassembly's, de zogenaamde contractassembly, kunnen worden gebruikt om meerdere platforms te richten die dezelfde set API's ondersteunen. .NET Standard biedt bijvoorbeeld de contractassembly, netstandard.dll, die de set algemene API's vertegenwoordigt die worden gedeeld tussen verschillende .NET-platforms. De implementaties van deze API's bevinden zich in verschillende assembly's op verschillende platforms, zoals mscorlib.dll in .NET Framework of System.Private.CoreLib.dll op .NET Core. Een bibliotheek die is gericht op .NET Standard, kan worden uitgevoerd op alle platforms die .NET Standard ondersteunen.
Referentieassembly's gebruiken
Als u bepaalde API's uit uw project wilt gebruiken, moet u verwijzingen toevoegen aan hun assembly's. U kunt verwijzingen toevoegen aan implementatieassembly's of aan referentieassembly's. Het is raadzaam om referentieassembly's te gebruiken wanneer deze beschikbaar zijn. Dit zorgt ervoor dat u alleen de ondersteunde API-leden in de doelversie gebruikt, bedoeld om te worden gebruikt door API-ontwerpers. Met behulp van de referentieassembly zorgt u ervoor dat u niet afhankelijk bent van implementatiedetails.
Referentieassembly's voor de .NET Framework-bibliotheken worden gedistribueerd met doelpakketten. U kunt ze verkrijgen door een zelfstandig installatieprogramma te downloaden of door een onderdeel te selecteren in het installatieprogramma van Visual Studio. Zie .NET Framework voor ontwikkelaars installeren voor meer informatie. Voor .NET Core en .NET Standard worden referentieassembly's automatisch gedownload (via NuGet) en waarnaar wordt verwezen. Voor .NET Core 3.0 en hoger bevinden de referentieassembly's voor het kernframework zich in het Microsoft.NETCore.App.Ref-pakket (het Microsoft.NETCore.App-pakket wordt in plaats daarvan gebruikt voor versies vóór 3.0).
Wanneer u verwijzingen toevoegt aan .NET Framework-assembly's in Visual Studio met behulp van het dialoogvenster Verwijzing toevoegen, selecteert u een assembly in de lijst. Visual Studio zoekt automatisch referentieassembly's die overeenkomen met de doelframeworkversie die in uw project is geselecteerd. Hetzelfde geldt voor het rechtstreeks toevoegen van verwijzingen aan MSBuild-project met behulp van het referentieprojectitem : u hoeft alleen de assemblynaam op te geven, niet het volledige bestandspad. Wanneer u verwijzingen toevoegt naar deze assembly's in de opdrachtregel met behulp van de -reference
compileroptie (in C# en in Visual Basic) of met behulp van de Compilation.AddReferences methode in de Roslyn-API, moet u handmatig referentieassemblybestanden opgeven voor de juiste doelplatformversie. .NET Framework-referentieassemblybestanden bevinden zich in % ProgramFiles(x86)%\Reference Assembly's\Microsoft\Framework\. NETFramework-map . Voor .NET Core kunt u de publicatiebewerking afdwingen om referentieassembly's voor uw doelplatform te kopiëren naar de submap publish/refs van uw uitvoermap door de PreserveCompilationContext
projecteigenschap in te stellen op true
. Vervolgens kunt u deze referentieassemblybestanden doorgeven aan de compiler. Met behulp DependencyContext
van het pakket Microsoft.Extensions.DependencyModel kunt u hun paden vinden.
Omdat ze geen implementatie bevatten, kunnen referentieassembly's niet worden geladen voor uitvoering. Als u dit probeert, resulteert dit in een System.BadImageFormatException. Als u de inhoud van een referentieassembly wilt onderzoeken, kunt u deze laden in de context met alleen reflectie in .NET Framework (met behulp van de Assembly.ReflectionOnlyLoad methode) of in MetadataLoadContext .NET en .NET Framework.
Referentieassembly's genereren
Het genereren van referentieassembly's voor uw bibliotheken kan handig zijn wanneer uw bibliotheekgebruikers hun programma's moeten bouwen op basis van veel verschillende versies van de bibliotheek. Het distribueren van implementatieassembly's voor al deze versies kan onpraktisch zijn vanwege hun grote grootte. Referentieassembly's zijn kleiner en distribueren ze als onderdeel van de SDK van uw bibliotheek vermindert de downloadgrootte en bespaart schijfruimte.
IDE's en buildhulpprogramma's kunnen ook gebruikmaken van referentieassembly's om de buildtijden te verminderen in het geval van grote oplossingen die bestaan uit meerdere klassebibliotheken. In incrementele buildscenario's wordt een project meestal opnieuw opgebouwd wanneer een van de invoerbestanden wordt gewijzigd, inclusief de assembly's waarvan het afhankelijk is. De implementatieassembly verandert wanneer de programmeur de implementatie van een lid wijzigt. De referentieassembly wordt alleen gewijzigd wanneer de openbare API wordt beïnvloed. Als u de referentieassembly dus gebruikt als invoerbestand in plaats van de implementatieassembly, kunt u in sommige gevallen de build van het afhankelijke project overslaan.
U kunt referentieassembly's genereren:
- Gebruik in een MSBuild-project de
ProduceReferenceAssembly
projecteigenschap. - Bij het compileren van een programma vanaf de opdrachtregel geeft u
-refonly
(C# / Visual Basic) of-refout
(C# / Visual Basic) compileropties op. - Wanneer u de Roslyn-API gebruikt, kunt u dit instellen EmitOptions.EmitMetadataOnly
true
op en EmitOptions.IncludePrivateMembers naarfalse
een object dat wordt doorgegeven aan de Compilation.Emit methode.
Als u referentieassembly's wilt distribueren met NuGet-pakketten, moet u deze opnemen in de submap ref\ onder de pakketmap in plaats van in de lib\ -submap die wordt gebruikt voor implementatieassembly's.
Structuur verwijzingsassembly's
Referentieassembly's zijn een uitbreiding van het gerelateerde concept, assembly's met alleen metagegevens. Assembly's met alleen metagegevens hebben hun methodeteksten vervangen door één throw null
hoofdtekst, maar bevatten alle leden behalve anonieme typen. De reden voor het gebruik van throw null
lichamen (in tegenstelling tot geen lichamen) is dat PEVerify kan worden uitgevoerd en doorgegeven (waardoor de volledigheid van de metagegevens wordt geverifieerd).
Naslagassembly's verwijderen metagegevens (privéleden) verder uit assembly's met alleen metagegevens:
- Een referentieassembly bevat alleen verwijzingen naar wat deze nodig heeft in het API-gebied. De echte assembly kan aanvullende verwijzingen hebben met betrekking tot specifieke implementaties. De referentieassembly voor
class C { private void M() { dynamic d = 1; ... } }
verwijst bijvoorbeeld niet naar typen die vereist zijn voordynamic
. - Privé-functieleden (methoden, eigenschappen en gebeurtenissen) worden verwijderd in gevallen waarin de verwijdering niet waarneembaar van invloed is op de compilatie. Als er geen internalsVisibleTo-kenmerken zijn, worden interne functieleden ook verwijderd.
De metagegevens in referentieassembly's blijven de volgende informatie behouden:
- Alle typen, inclusief privé- en geneste typen.
- Alle kenmerken, zelfs interne kenmerken.
- Alle virtuele methoden.
- Expliciete interface-implementaties.
- Expliciet geïmplementeerde eigenschappen en gebeurtenissen, omdat hun accessors virtueel zijn.
- Alle velden van structuren.
Referentieassembly-assembly's bevatten een referentieassembly-kenmerk op assemblyniveau. Dit kenmerk kan worden opgegeven in de bron; vervolgens hoeft de compiler deze niet te synthetiseren. Vanwege dit kenmerk weigeren runtimes referentieassembly's te laden voor uitvoering (maar ze kunnen wel worden geladen in de modus alleen reflectie).
De details van de exacte referentieassemblystructuur zijn afhankelijk van de compilerversie. Nieuwere versies kunnen ervoor kiezen om meer metagegevens uit te sluiten als deze worden bepaald als niet van invloed op het openbare API-oppervlak.
Notitie
Informatie in deze sectie is alleen van toepassing op referentieassemblys die zijn gegenereerd door Roslyn-compilers vanaf C#-versie 7.1 of Visual Basic versie 15.3. De structuur van referentieassembly's voor .NET Framework- en .NET Core-bibliotheken kan in sommige details verschillen, omdat ze hun eigen mechanisme gebruiken voor het genereren van referentieassembly's. Ze kunnen bijvoorbeeld volledig lege methodeteksten hebben in plaats van het throw null
lichaam. Maar het algemene principe is nog steeds van toepassing: ze hebben geen bruikbare methodeimplementaties en bevatten alleen metagegevens voor leden die een waarneembare impact hebben vanuit het perspectief van een openbare API.