Dela via


Migrera din Windows 8.x-app till .NET Native

.NET Native tillhandahåller statisk kompilering av appar i Microsoft Store eller på utvecklarens dator. Detta skiljer sig från den dynamiska kompilering som utförs för Windows 8.x-appar (även tidigare kallade Microsoft Store-appar) av jit-kompilatorn (just-in-time) eller Native Image Generator (Ngen.exe) på enheten. Trots skillnaderna försöker .NET Native upprätthålla kompatibiliteten med .NET för Windows 8.x-appar. För det mesta fungerar även saker som fungerar på .NET för Windows 8.x-appar med .NET Native. I vissa fall kan du dock stöta på beteendeförändringar. I det här dokumentet beskrivs dessa skillnader mellan standardapparna .NET för Windows 8.x och .NET Native inom följande områden:

Allmänna körningstidskillnader

  • Undantag, till exempel TypeLoadException, som genereras av JIT-kompilatorn när en app körs på CLR (Common Language Runtime) resulterar vanligtvis i kompileringsfel när den bearbetas av .NET Native.

  • Anropa inte metoden GC.WaitForPendingFinalizers från en apps användargränssnittstråd. Detta kan leda till ett dödläge på .NET Native.

  • Förlita dig inte på anropsordning för statiska klasskonstruktorer. I .NET Native skiljer sig anropsordningen från ordningen på standard-runtime. Även med standardkörtiden bör du inte förlita dig på utförandeordningen för statiska klasskonstruktorer.

  • Oändlig loopning utan att göra ett anrop (till exempel while(true);) i någon tråd kan stoppa appen. På samma sätt kan stora eller oändliga väntetider stoppa appen.

  • Vissa allmänna initieringscykler utlöser inte undantag i .NET Native. Följande kod genererar till exempel ett TypeLoadException undantag för standard-CLR. I .NET Native gör det inte det.

    using System;
    
    struct N<T> {}
    struct X { N<X> x; }
    
    public class Example
    {
       public static void Main()
       {
          N<int> n = new N<int>();
          X x = new X();
       }
    }
    
  • I vissa fall tillhandahåller .NET Native olika implementeringar av .NET Framework-klassbibliotek. Ett objekt som returneras från en metod implementerar alltid medlemmar av den returnerade typen. Men eftersom dess stödimplementering skiljer sig åt kanske du inte kan omvandla den till samma uppsättning typer som på andra .NET Framework-plattformar. I vissa fall kanske du till exempel inte kan omvandla det IEnumerable<T> gränssnittsobjektet som returneras med metoder som TypeInfo.DeclaredMembers eller TypeInfo.DeclaredProperties till T[].

  • WinInet-cachen är inte aktiverad som standard på .NET för Windows 8.x-appar, men den är på .NET Native. Detta förbättrar prestanda men har konsekvenser för arbetsminne. Ingen utvecklaråtgärd krävs.

Skillnader i dynamisk programmering

.NET Native länkar statiskt i kod från .NET Framework för att göra koden applokal för maximal prestanda. Binära storlekar måste dock förbli små, så hela .NET Framework kan inte tas in. Den interna .NET-kompilatorn löser den här begränsningen med hjälp av en beroendere reducer som tar bort referenser till oanvänd kod. .NET Native kanske dock inte underhåller eller genererar viss typinformation och kod när den informationen inte kan härledas statiskt vid kompileringstillfället, utan i stället hämtas dynamiskt vid körning.

.NET Native möjliggör reflektion och dynamisk programmering. Alla typer kan dock inte markeras för reflektion eftersom det skulle göra den genererade kodstorleken för stor (särskilt eftersom det stöds att reflektera över offentliga API:er i .NET Framework). .NET Native-kompilatorn gör smarta val om vilka typer som ska stödja reflektion och behåller metadata och genererar endast kod för dessa typer.

Databindning kräver till exempel att en app kan mappa egenskapsnamn till funktioner. I .NET för Windows 8.x-appar använder den vanliga språkkörningen automatiskt reflektion för att tillhandahålla den här funktionen för hanterade typer och offentligt tillgängliga interna typer. I .NET Native innehåller kompilatorn automatiskt metadata för typer som du binder data till.

.NET Native-kompilatorn kan också hantera vanliga generiska typer som List<T> och Dictionary<TKey,TValue>, som fungerar utan att det krävs några tips eller direktiv. Nyckelordet dynamisk stöds också inom vissa gränser.

Anmärkning

Du bör testa alla dynamiska kodsökvägar noggrant när du porterar din app till .NET Native.

Standardkonfigurationen för .NET Native räcker för de flesta utvecklare, men vissa utvecklare kanske vill finjustera sina konfigurationer med hjälp av en körningsdirektivfil (.rd.xml). I vissa fall kan .NET Native-kompilatorn dessutom inte avgöra vilka metadata som måste vara tillgängliga för reflektion och förlitar sig på tips, särskilt i följande fall:

  • Vissa konstruktioner som Type.MakeGenericType och MethodInfo.MakeGenericMethod kan inte fastställas statiskt.

  • Eftersom kompilatorn inte kan fastställa instansieringarna måste en allmän typ som du vill reflektera över anges av körningsdirektiv. Detta beror inte bara på att all kod måste inkluderas, utan på att reflektion över generiska typer kan bilda en oändlig cykel (till exempel när en generisk metod anropas på en generisk typ).

Anmärkning

Körningsdirektiv definieras i en körningsdirektivfil (.rd.xml). Allmän information om hur du använder den här filen finns i Komma igång. Information om körningsdirektiven finns i Körningsdirektiv (rd.xml) Referens till konfigurationsfil.

.NET Native innehåller även profileringsverktyg som hjälper utvecklaren att avgöra vilka typer utanför standarduppsättningen som ska ha stöd för reflektion.

Det finns ett antal andra individuella reflektionsrelaterade skillnader i beteende mellan .NET för Windows 8.x-appar och .NET Native.

I .NET Native:

  • Privat reflektion över typer och medlemmar i .NET Framework-klassbiblioteket stöds inte. Du kan dock reflektera över dina egna privata typer och medlemmar, samt typer och medlemmar i bibliotek från tredje part.

  • Egenskapen ParameterInfo.HasDefaultValue returnerar korrekt false för ett ParameterInfo objekt som representerar ett returvärde. I .NET för Windows 8.x-appar returneras true. Mellanliggande språk (IL) stöder inte detta direkt, och tolkningen lämnas till språket.

  • Offentliga medlemmar i strukturerna RuntimeFieldHandle och RuntimeMethodHandle stöds inte. Dessa typer stöds endast för LINQ, uttrycksträd och initiering av statisk matris.

  • RuntimeReflectionExtensions.GetRuntimeProperties och RuntimeReflectionExtensions.GetRuntimeEvents inkluderar dolda medlemmar i basklasserna och kan därför åsidosättas utan explicit åsidosättande. Detta gäller även för andra RuntimeReflectionExtensions.GetRuntime* metoder.

  • Type.MakeArrayType och Type.MakeByRefType misslyckas inte när du försöker skapa vissa kombinationer (till exempel en matris med byref objekt).

  • Du kan inte använda reflektion för att anropa medlemmar som har pekarparametrar.

  • Du kan inte använda reflektion för att hämta eller ange ett pekarfält.

  • När argumentantalet är fel och typen av ett av argumenten är felaktigt, genererar .NET Native en ArgumentException i stället för en TargetParameterCountException.

  • Binär serialisering av undantag stöds vanligtvis inte. Därför kan icke-serialiserbara objekt läggas till i Exception.Data ordlista.

Scenarier och API:er som inte stöds

I följande avsnitt visas scenarier och API:er som inte stöds för allmän utveckling, interop och tekniker som HTTPClient och Windows Communication Foundation (WCF):

Allmänna utvecklingsskillnader

Värdetyper

  • Om du åsidosätter metoderna ValueType.Equals och ValueType.GetHashCode för en värdetyp ska du inte anropa basklassimplementeringarna. I .NET för Windows 8.x-appar förlitar sig dessa metoder på reflektion. Vid kompilering genererar .NET Native en implementering som inte förlitar sig på runtime-reflektion. Det innebär att om du inte åsidosätter dessa två metoder fungerar de som förväntat eftersom .NET Native genererar implementeringen vid kompileringstillfället. Att åsidosätta dessa metoder men anropa basklassimplementeringen resulterar dock i ett undantag.

  • Värdetyper som är större än 1 megabyte stöds inte.

  • Värdetyper kan inte ha en parameterlös konstruktor i .NET Native. (C# och Visual Basic förbjuder parameterlösa konstruktorer för värdetyper. Dessa kan dock skapas i IL.)

arrayer

  • Matriser med en lägre gräns än noll stöds inte. Vanligtvis skapas dessa matriser genom att anropa Array.CreateInstance(Type, Int32[], Int32[])-överladdning.

  • Dynamiskt skapande av flerdimensionella matriser stöds inte. Sådana matriser skapas vanligtvis genom att anropa en överlagring av metoden Array.CreateInstance som innehåller en lengths parameter eller genom att anropa metoden Type.MakeArrayType(Int32).

  • Flerdimensionella matriser som har fyra eller fler dimensioner stöds inte; det vill säga, deras Array.Rank-egenskapsvärde är fyra eller större. I stället, använd ojämna fält (en matris av matriser). Till exempel är array[x,y,z] ogiltigt, men array[x][y][z] är det inte.

  • Varians för flerdimensionella matriser stöds inte och orsakar ett InvalidCastException-undantag vid körningstid.

Generiska typer

  • Oändlig generisk typexpansion resulterar i ett kompilatorfel. Den här koden kan till exempel inte kompileras:

    class A<T> {}
    
    class B<T> : A<B<A<T>>>
    {}
    

pekare

  • Matriser med pekare stöds inte.

  • Du kan inte använda reflektion för att hämta eller ange ett pekarfält.

serialisering

Attributet KnownTypeAttribute(String) stöds inte. Använd attributet KnownTypeAttribute(Type) i stället.

Resurser

Användningen av lokaliserade resurser med klassen EventSource stöds inte. Egenskapen EventSourceAttribute.LocalizationResources definierar inte lokaliserade resurser.

Ombuden

Delegate.BeginInvoke och Delegate.EndInvoke stöds inte.

Diverse API:er

  • Egenskapen TypeInfo.GUID genererar ett PlatformNotSupportedException undantag om ett GuidAttribute-attribut inte tillämpas på typen. GUID används främst för COM-support.

  • Metoden DateTime.Parse parsar strängar som innehåller korta datum i .NET Native. Den upprätthåller dock inte kompatibilitet med vissa ändringar i datum- och tidsparsning.

  • BigInteger.ToString ("E") avrundas korrekt i .NET Native. I vissa versioner av CLR trunkeras resultatsträngen i stället för avrundad.

HttpClient-skillnader

I .NET Native använder klassen HttpClientHandler internt WinINet (via klassen HttpBaseProtocolFilter) i stället för klasserna WebRequest och WebResponse som används i standardapparna .NET för Windows 8.x. WinINet stöder inte alla konfigurationsalternativ som HttpClientHandler-klassen stöder. Som ett resultat:

  • Några av funktionsegenskaperna på HttpClientHandler returnerar false på .NET Native, medan de returnerar true i standardapparna för .NET för Windows 8.x.

  • En del av konfigurationsegenskapen get-accessorer returnerar alltid ett fast värde på .NET Native som skiljer sig från standardkonfigurerbart värde i .NET för Windows 8.x-appar.

Några ytterligare beteendeskillnader beskrivs i följande underavsnitt.

Proxyserver

Klassen HttpBaseProtocolFilter stöder inte konfiguration eller åsidosättande av proxyn per begäran. Det innebär att alla begäranden på .NET Native använder den systemkonfigurerade proxyservern eller ingen proxyserver, beroende på värdet för egenskapen HttpClientHandler.UseProxy. I .NET för Windows 8.x-appar definieras proxyservern av egenskapen HttpClientHandler.Proxy. Om du anger ett annat värde för HttpClientHandler.Proxy än null på .NET Native genereras ett PlatformNotSupportedException undantag. Egenskapen HttpClientHandler.SupportsProxy returnerar false på .NET Native, medan den returnerar true i standard-.NET Framework för Windows 8.x-appar.

Automatisk omdirigering

Klassen HttpBaseProtocolFilter tillåter inte att det maximala antalet automatiska omdirigeringar konfigureras. Värdet för egenskapen HttpClientHandler.MaxAutomaticRedirections är 50 som standard i standarden .NET för Windows 8.x-appar och kan ändras. På .NET Native är värdet för den här egenskapen 10 och om du försöker ändra den genereras ett PlatformNotSupportedException undantag. Egenskapen HttpClientHandler.SupportsRedirectConfiguration returnerar false på .NET Native, medan den returnerar true i .NET för Windows 8.x-appar.

Automatisk dekomprimering

Med .NET för Windows 8.x-appar kan du ange egenskapen HttpClientHandler.AutomaticDecompression till Deflate, GZip, både Deflate och GZipeller None. .NET Native stöder endast Deflate tillsammans med GZipeller None. Om du försöker ställa in egenskapen AutomaticDecompression till antingen Deflate eller GZip kommer den tyst att ställas in på både Deflate och GZip.

Cookies

Cookiehantering utförs samtidigt av HttpClient och WinINet. Cookies från CookieContainer kombineras med cookies i WinINet-cookiecachen. Om du tar bort en cookie från CookieContainer förhindrar HttpClient från att skicka cookien, men om cookien redan har setts av WinINet och cookies inte har tagits bort av användaren skickar WinINet den. Det går inte att programmatiskt ta bort en cookie från WinINet med hjälp av api:et HttpClient, HttpClientHandlereller CookieContainer. Om egenskapen HttpClientHandler.UseCookies anges till false slutar bara HttpClient att sluta skicka cookies. WinINet kan fortfarande inkludera sina cookies i begäran.

Autentiseringsuppgifter

I .NET för Windows 8.x-appar fungerar egenskaperna HttpClientHandler.UseDefaultCredentials och HttpClientHandler.Credentials oberoende av varandra. Dessutom accepterar egenskapen Credentials alla objekt som implementerar ICredentials-gränssnittet. I .NET Native orsakar inställning av egenskapen UseDefaultCredentials till true att egenskapen Credentials blir null. Dessutom kan egenskapen Credentials endast anges till null, DefaultCredentialseller ett objekt av typen NetworkCredential. Om du tilldelar andra ICredentials objekt, varav den populäraste är CredentialCache, till egenskapen Credentials, utlöser en PlatformNotSupportedException.

Andra funktioner som inte stöds eller inte kan konfigureras

I .NET Native:

Interoperabilitetsskillnader

Inaktuella API:er

Ett antal api:er som används sällan för samverkan med hanterad kod har blivit inaktuella. När de används med .NET Native kan dessa API:er utlösa ett NotImplementedException eller PlatformNotSupportedException undantag, eller resultera i ett kompilatorfel. I .NET för Windows 8.x-appar markeras dessa API:er som föråldrade, men om du anropar dem genereras en kompilatorvarning i stället för ett kompilatorfel.

Inaktuella API:er för VARIANT serialisering omfattar:

UnmanagedType.Struct stöds, men det utlöser ett undantag i vissa scenarier, till exempel när det används med IDispatch- eller byref varianter.

Inaktuella API:er för IDispatch support omfattar:

Inaktuella API:er för klassiska COM-händelser är:

Inaktuella API:er i System.Runtime.InteropServices.ICustomQueryInterface-gränssnittet, som inte stöds i .NET Native, inkluderar:

Andra interop-funktioner som inte stöds är:

Sällan använda marshaling-API:er

Plattformanrop och COM interop-kompatibilitet

De flesta scenarier för plattformsanrop och COM-interop stöds fortfarande i .NET Native. I synnerhet stöds all samverkan med Windows Runtime-API:er (WinRT) och all marshaling som krävs för Windows Runtime. Detta inkluderar att samla stöd för:

.NET Native stöder dock inte följande:

Det går inte att använda reflektion för att anropa en plattformsanropsmetod. Du kan kringgå den här begränsningen genom att omsluta metodanropet i en annan metod och använda reflection för att anropa den omslutande metoden i stället.

Andra skillnader från .NET-API:er för Windows 8.x-appar

I det här avsnittet visas de återstående API:er som inte stöds i .NET Native. Den största uppsättningen API:er som inte stöds är API:erna för Windows Communication Foundation (WCF).

DataAnnotations (System.ComponentModel.DataAnnotations)

Typerna i namnrymderna System.ComponentModel.DataAnnotations och System.ComponentModel.DataAnnotations.Schema stöds inte i .NET Native. Dessa inkluderar följande typer som finns i .NET för Windows 8.x-appar:

Visual Basic

Visual Basic stöds för närvarande inte i .NET Native. Följande typer i Microsoft.VisualBasic och Microsoft.VisualBasic.CompilerServices namnområden är inte tillgängliga i .NET Native:

Reflektionskontext (System.Reflection.Context namespace)

Klassen System.Reflection.Context.CustomReflectionContext stöds inte i .NET Native.

RTC (System.Net.Http.Rtc)

Klassen System.Net.Http.RtcRequestFactory stöds inte i .NET Native.

Windows Communication Foundation (WCF) (System.ServiceModel.*)

Typerna i namnrymderna System.ServiceModel.* stöds inte i .NET Native. Dessa inkluderar följande typer:

Skillnader i serialiserare

Följande skillnader gäller serialisering och deserialisering med klasserna DataContractSerializer, DataContractJsonSerializeroch XmlSerializer:

skillnader i Visual Studio

undantag och felsökning

När du kör appar som kompilerats med hjälp av .NET Native i felsökningsprogrammet aktiveras undantag från första chansen för följande undantagstyper:

Skapa appar

Använd de x86-byggverktyg som används som standard av Visual Studio. Vi rekommenderar inte att du använder AMD64 MSBuild-verktygen, som finns i C:\Program Files (x86)\MSBuild\12.0\bin\amd64; dessa kan skapa byggproblem.

Profileringsverktyg

  • Visual Studio CPU Profiler och XAML Memory Profiler visar inte Just-My-Code korrekt.

  • XAML Memory Profiler visar inte hanterade heap-data korrekt.

  • CPU Profiler identifierar inte moduler korrekt och visar prefixerade funktionsnamn.

Enhetstestbiblioteksprojekt

Aktivering av .NET Native i ett enhetstestbibliotek för ett Windows 8.x-appprojekt stöds inte och gör att projektet inte kan byggas.

Se även