Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
De undantag som kastas vid anrop av reflection-invoke-API:er har ändrats.
Tidigare beteende
Tidigare, när en anropad metod som returnerar ett värde med referens returnerade
null, kastades en NullReferenceException .För konstruktorer utlöstes följande undantag:
- Tillfälliga undantag, inklusive OutOfMemoryException.
- Ett OverflowException när ett negativt värde skickades för längdparametern för en matris.
När
nullskickades för en byref-liknande parameter utanrefmodifieraren (d.v.s. skickades som värde), utlöstes inget undantag och den körningen ersatte nullvärdet med ett standardvärde.
Nytt beteende
Från och med .NET 7:
I stället för att kasta det ursprungliga undantaget (inklusive NullReferenceException och OutOfMemoryException som nämns i Föregående beteende) kastas TargetInvocationException i alla fall när de inledande
Invoke()parametrarna har verifierats. Det inre undantaget innehåller det ursprungliga undantaget.NotSupportedException genereras när
nullskickas för en byref-liknande parameter när parametern deklareras som "efter värde" (det vill sägs att den inte har någonrefmodifierare). För det relaterade fallet när parametern skickas med referens (dvs. harrefmodifieraren) är det tidigare och det nya beteendet detsamma: en NotSupportedException kastas.
Version lanserad
.NET 7
Typ av brytande ändring
Den här ändringen kan påverka binär kompatibilitet.
Orsak till ändring
Om du kastar TargetInvocationException i stället för det ursprungliga undantaget blir upplevelsen mer konsekvent. Det ordnar korrekt undantag som orsakas av valideringen av inkommande parametrar (som inte är omslutna med TargetInvocationException) mot undantag som utlöses på grund av implementeringen av målmetoden (som är omslutna med TargetInvocationException). Konsekventa regler ger mer konsekventa upplevelser för olika implementeringar av CLR och API Invoke :er.
Ändringen att kasta NotSupportedException när en byref-liknande typ skickas till ett Invoke() API korrigerar ett misstag i den ursprungliga implementeringen, som inte kastade. Den ursprungliga implementeringen visade att ref struct typer stöds av API:erna Invoke() när de inte är det. Eftersom de aktuella Invoke() API:erna använder System.Object för parametertyper, och en ref struct typ inte kan boxas till System.Object, är det ett scenario som inte stöds.
Rekommenderad åtgärd
Om du inte använder BindingFlags.DoNotWrapExceptions när du anropar Invoke()och du har catch instruktioner runt API:erna Invoke() för andra undantag än TargetInvocationExceptionkan du överväga att ändra eller ta bort dessa catch instruktioner. De andra undantagen kastas inte längre som ett resultat av anropet. Om du däremot fångar undantag från argumentvalidering som inträffar innan du försöker anropa målmetoden bör du behålla dessa catch instruktioner. Ogiltiga argument som valideras innan ett försök att anropa görs, kastas utan att omslutas med TargetInvocationException och har inte ändrat betydelse.
Överväg att använda BindingFlags.DoNotWrapExceptions så att TargetInvocationException aldrig kastas. I det här fallet kommer det ursprungliga undantaget inte att omslutas av en TargetInvocationException. I de flesta fall ökar chanserna att diagnostisera det faktiska problemet genom att inte omsluta undantaget, eftersom inte alla verktyg för undantagsrapportering visar det inre undantaget. Genom att använda BindingFlags.DoNotWrapExceptionsgenereras dessutom samma undantag som när metoden anropas direkt (utan reflektion). Detta är önskvärt i de flesta fall, eftersom valet av om reflektion används eller inte kan vara godtyckligt eller en implementeringsinformation som inte behöver dyka upp för anroparen.
I det sällsynta fallet att du behöver skicka ett standardvärde till en metod via reflektion som innehåller en byref-liknande parameter som skickas "efter värde" kan du lägga till en omslutningsmetod som utelämnar parametern och anropar målmetoden med ett standardvärde för parametern.
Berörda API:er
- System.Reflection.MethodBase.Invoke(Object, Object[])
- System.Reflection.MethodBase.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.ConstructorInfo.Invoke(Object[])
- System.Reflection.ConstructorInfo.Invoke(BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.PropertyInfo.GetValue(Object)
- System.Reflection.PropertyInfo.GetValue(Object, Object[])
- System.Reflection.PropertyInfo.GetValue(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.PropertyInfo.SetValue(Object, Object)
- System.Reflection.PropertyInfo.SetValue(Object, Object, Object[])
- System.Reflection.PropertyInfo.SetValue(Object, Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Reflection.Emit.DynamicMethod.Invoke(Object, BindingFlags, Binder, Object[], CultureInfo)
- System.Activator.CreateInstance(Type, Object[])
- System.Activator.CreateInstance(Type, Object[], Object[])
- System.Activator.CreateInstance(Type, BindingFlags, Binder, Object[], CultureInfo)
- System.Activator.CreateInstance(Type, BindingFlags, Binder, Object[], CultureInfo, Object[])
- System.Activator.CreateInstance(String, String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[])