Mój współpracownik i ja debugujemy problem w usłudze WCF, nad którą pracuje, gdzie długość łańcucha nie jest poprawnie oceniana. On pracuje tej metody do testów jednostkowych metody w służbie WCF:Niepoprawna długość łańcucha znaków
// Unit test method
public void RemoveAppGroupTest()
{
string addGroup = "TestGroup";
string status = string.Empty;
string message = string.Empty;
appActiveDirectoryServicesClient.RemoveAppGroup("AOD", addGroup, ref status, ref message);
}
// Inside the WCF service
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void RemoveAppGroup(string AppName, string GroupName, ref string Status, ref string Message)
{
string accessOnDemandDomain = "MyDomain";
RemoveAppGroupFromDomain(AppName, accessOnDemandDomain, GroupName, ref Status, ref Message);
}
public AppActiveDirectoryDomain(string AppName, string DomainName)
{
if (string.IsNullOrEmpty(AppName))
{
throw new ArgumentNullException("AppName", "You must specify an application name");
}
}
Próbowaliśmy wejść do kodu źródłowego .NET, aby zobaczyć, jakie wartości string.IsNullOrEmpty
otrzymywał, ale IDE drukowane tę wiadomość, gdy staraliśmy się oceń zmienną: "Nie można uzyskać wartości wartości lokalnej lub argumentowej", ponieważ nie jest dostępna w tym wskaźniku instrukcji, prawdopodobnie dlatego, że została zoptymalizowana ". (Żaden z zaangażowanych projektów nie ma włączonych optymalizacji). Postanowiliśmy więc spróbować jawnie ustawić wartość zmiennej wewnątrz samej metody, tuż przed sprawdzeniem długości - ale to nie pomogło.
// Lets try this again.
public AppActiveDirectoryDomain(string AppName, string DomainName)
{
// Explicitly set the value for testing purposes.
AppName = "AOD";
if (AppName == null)
{
throw new ArgumentNullException("AppName", "You must specify an application name");
}
if (AppName.Length == 0)
{
// This exception gets thrown, even though it obviously isn't a zero length string.
throw new ArgumentNullException("AppName", "You must specify an application name");
}
}
Naprawdę wyciągamy włosy z tego. Czy ktoś inny doświadczył takiego zachowania? Wszelkie wskazówki dotyczące debugowania go?
Oto MSIL dla obiektu AppActiveDirectoryDomain
, gdzie zachowanie ma miejsce:
.method public hidebysig specialname rtspecialname instance void .ctor(string AppName, string DomainName) cil managed
{
.maxstack 5
.locals init (
[0] class [System]System.Net.NetworkCredential ldapCredentials,
[1] string[] creds,
[2] string userName,
[3] class [mscorlib]System.ArgumentNullException exc,
[4] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.DirectoryContext directoryContext,
[5] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.Domain domain,
[6] class [System.DirectoryServices.Protocols]System.DirectoryServices.Protocols.LdapException V_6,
[7] class [mscorlib]System.Exception V_7,
[8] bool CS$4$0000,
[9] char[] CS$0$0001,
[10] string[] CS$0$0002)
L_0000: ldarg.0
L_0001: ldsfld string [mscorlib]System.String::Empty
L_0006: stfld string MyNamespace.MyClass.AppActiveDirectoryDomain::appOU
L_000b: ldarg.0
L_000c: call instance void [mscorlib]System.Object::.ctor()
L_0011: nop
L_0012: nop
L_0013: ldstr "AOD"
L_0018: call bool [mscorlib]System.String::IsNullOrEmpty(string)
L_001d: ldc.i4.0
L_001e: ceq
L_0020: stloc.s CS$4$0000
L_0022: ldloc.s CS$4$0000
L_0024: brtrue.s L_0037
L_0026: nop
L_0027: ldstr "AppName"
L_002c: ldstr "You must specify an application name"
L_0031: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string)
L_0036: throw
A MSIL dla wywołania string.IsNullOrEmpty
:
.method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: brfalse.s L_000d
L_0003: ldarg.0
L_0004: callvirt instance int32 System.String::get_Length()
L_0009: ldc.i4.0
L_000a: ceq
L_000c: ret
L_000d: ldc.i4.1
L_000e: ret
}
Edit:
Oto zrzut ekranu zmiennej w oknie „oglądać” w momencie ArgumentNullException jest wyrzucany: http://imgur.com/xQm4J.png
Również drugi zrzut ekranu przedstawiający wyjątek wyrzucane podczas sprawdzania długości łańcucha, po wyraźnie oświadczając to 5 linii powyżej: http://imgur.com/lSrk9.png
Aktualizacja # 3: Próbowaliśmy zmienić nazwę zmiennej lokalnej, która przejdzie kontrolę zerową i kontrolę długości, ale nie powiedzie się, gdy zadzwonimy pod numer string.IsNullOrEmpty
. Zobacz ten zrzut ekranu: http://imgur.com/Z57AA.png.
Odpowiedzi:
nie używamy żadnych narzędzi, które modyfikują MSIL. Przeprowadziliśmy czyszczenie, a także ręcznie usunęliśmy wszystkie pliki z katalogów kompilacji i wymusiliśmy przebudowę ... ten sam wynik.
Następująca instrukcja jest wartością true i wchodzi do bloku if:
if (string.IsNullOrEmpty("AOD")) { /* */ }
.Konstruktor nazywa się tak:
try { using (AppActiveDirectoryDomain domain = new AppActiveDirectoryDomain(AppName, DomainName)) { } }
To natychmiast wewnątrz metody usługi WCF samego; AppName i DomainName są parametrami połączenia. Nawet pomijając te parametry i używając nowych ciągów, nadal otrzymujemy błędy.
Jeśli umieścisz punkt przerwania na wyjątku, który zostanie zgłoszony, i dodasz do listy zegarków nazwy "AppName" i "AppName.Length", co one pokazują? –
Pokazują one "AppName ==" AOD "" i "AppName.Length == 3" - więc oceniają poprawnie. Załączam zrzut ekranu na dole mojego pytania. –
Możesz sprawić, że test będzie jeszcze mniej niejednoznaczny: 'if (" AOD ".Length == 0) throw ...'. Wyklucza to zmienną 'AppName' jako źródło twoich problemów. Jeśli wyjątek jest nadal rzucany, nic nie można z tym zrobić. – stakx