2012-03-29 3 views
2

Wenn ich in Reflector prüfen FieldInfo.SetValueDirect sieht es wie folgt aus:Wie kann eine Methode nur eine NotImplementedException enthalten und trotzdem ohne zu werfen ausgeführt werden?

C#, .NET 4.0:

[CLSCompliant(false)] 
public virtual void SetValueDirect(TypedReference obj, object value) 
{ 
    throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS")); 
} 

Und wie IL:

.method public hidebysig newslot virtual instance void SetValueDirect(valuetype System.TypedReference obj, object 'value') cil managed 
{ 
    .custom instance void System.CLSCompliantAttribute::.ctor(bool) = { bool(false) } 
    .maxstack 8 
    L_0000: ldstr "NotSupported_AbstractNonCLS" 
    L_0005: call string System.Environment::GetResourceString(string) 
    L_000a: newobj instance void System.NotSupportedException::.ctor(string) 
    L_000f: throw 
} 

Allerdings, wenn ich den folgenden Code es funktioniert einfach.

// test struct: 
public struct TestFields 
{ 
    public int MaxValue; 
    public Guid SomeGuid; // req for MakeTypeRef, which doesn't like primitives 
} 


[Test] 
public void SettingFieldThroughSetValueDirect() 
{ 

    TestFields testValue = new TestFields { MaxValue = 1234 }; 

    FieldInfo info = testValue.GetType().GetField("MaxValue"); 
    Assert.IsNotNull(info); 

    // TestFields.SomeGuid exists as a field 
    TypedReference reference = TypedReference.MakeTypedReference(
     testValue, 
     new [] { fields.GetType().GetField("SomeGuid") }); 

    int value = (int)info.GetValueDirect(reference,); 
    info.SetValueDirect(reference, 4096); 

    // assert that this actually worked 
    Assert.AreEqual(4096, fields.MaxValue); 

} 

Kein Fehler wird ausgelöst. Gleiches gilt für GetValueDirect. Meine Schätzung basierend auf dem Namen der Ressource ist, wird dies nur ausgelöst, wenn der Code CLSCompliant sein muss, aber wo ist der Körper der Methode? Oder, anders ausgedrückt, wie kann ich den tatsächlichen Körper der Methode reflektieren?

Antwort

5

Es ist eine virtuelle Methode. Vermutlich gibt Type.GetField() einen abgeleiteten Typ mit der realen Implementierung zurück - versuchen Sie, info.GetType() zu drucken. (Ich habe gerade an meiner Box versucht, und es zeigte System.RtFieldInfo zum Beispiel.)

3

Debugger zeigt als testValue.GetType().GetField("MaxValue") gibt RtFieldInfo zurück, die von RuntimeFieldInfo abgeleitet ist, die von FieldInfo abgeleitet ist. Wahrscheinlich wurde diese Methode in einer dieser Klassen überschrieben. Höchstwahrscheinlich, weil es verschiedene Implementierungen von FieldInfo für Laufzeittypen und -typen von reflection-only geladenen Assemblies gibt

+0

Jon war schneller als das Licht wie üblich, aber Ihre Schlussfolgerung ist gleich seinem;). – Abel

Verwandte Themen