2012-07-01 17 views
34

Ich habe eine (C#) Funktion ähnlich der folgenden.SecurityException: ECall-Methoden müssen in ein Systemmodul gepackt werden

private static bool SpecialCase = false; 

public void Foo() 
{ 
    if (SpecialCase) 
    { 
     InternalMethod(); 
     return; 
    } 

    Console.WriteLine(); 
} 

[MethodImpl(MethodImplOptions.InternalCall)] 
private static extern void InternalMethod(); 

Wenn ich das mit dem .NET Framework 4 innerhalb des Debugger ausführen, druckt das Verfahren erfolgreich leere Zeile auf die Konsole und kehrt zurück. Wenn ich es außerhalb des Debugger ausführen, wirft es eine Ausnahme mit der folgenden Meldung:

System.Security.SecurityException: ECall methods must be packaged into a system module. 

Es scheint die Ausnahme ausgelöst wird, wenn die JIT-Compiler die Methode im Gegensatz zu kompiliert, wenn (falls) InternalMethod genannt wird. Gibt es irgendetwas, was ich tun kann (z. B. Attribute), um der CLI zu sagen, dass sie entweder die SecurityException nicht auslöst oder die Ausnahme solange verzögert, bis die Methode tatsächlich aufgerufen wird?

Seitliche Anmerkung zum Anwendungsfall: Das Feld SpecialCase ist effektiv falsch, wenn es mit Microsoft .NET Framework ausgeführt wird, und wahr, wenn es unter einer anderen (spezifischen) CLI-Implementierung ausgeführt wird. Wenn Sie unter Microsoft .NET Framework ausführen, ist der Aufruf an InternalMethod effektiv nicht erreichbar.

+0

Können Sie es in einer normalen Methode umhüllen? – SLaks

+1

Ja, es scheint, dass der Aufruf einer Wrapper-Methode wie die folgende die Ausnahme vermeidet. Der Nachteil ist, dass diese Praxis zu noch verwirrenden Codepfaden in einem bereits komplexen Algorithmus führen würde. Daher bevorzuge ich eine sauberere Lösung, wenn eine gefunden wird. 'private static void InternerMethodWrapper() {InternalMethod(); } ' –

+0

BTW Es passiert auch auf' .NET 4.5.2' aber in beiden Frameworks (beide Frameworks hat die gleiche 'CLR' sowieso) nur in 'Release' nicht in' Debug', haben Sie in Betracht gezogen, im 'Debug'-Modus zu arbeiten ? –

Antwort

1

Attribut hinzufügen [ComImport] auf Ihre Klassendeklaration

2

Sie können die compiler directives as a possible option überprüfen. Im Gegensatz zur Verwendung einer Laufzeit "if" bestimmt dies, ob der Aufruf überhaupt im kompilierten Code enthalten ist, anstatt ihn immer in den Code zu kompilieren und zu bestimmen, ob er zur Laufzeit aufgerufen werden soll (was auch der Fall ist) spät, basierend auf Ihrer Analyse).

Ihr Anwendungsfall scheint ein Test-/Validierungsszenario zu sein, was bedeutet, dass Sie ihn nicht in den Code kompiliert benötigen, außer wenn der interne Anruf tatsächlich ausgeführt wird.

Beachten Sie, dass Sie, wenn Ihr Anwendungsfall eine Nicht-.NET-Laufzeitumgebung umfasst, mehr Informationen bereitstellen sollten, da dies die richtige Antwort drastisch ändern könnte.

Verwandte Themen