Question

If I check in Reflector for FieldInfo.SetValueDirect it looks as follows:

C#, .NET 4.0:

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

And as 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 
}

However, if I run the following code, it just works.

// 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);

}

No error is thrown. Same is true for GetValueDirect. My guess based on the name of the resource is, this is only thrown if the code must be CLSCompliant, but where is the body of the method? Or, put another way, how can I reflect the actual body of the method?

Était-ce utile?

La solution

It's a virtual method. Presumably Type.GetField() is returning a derived type with the real implementation - try printing info.GetType(). (I've just tried on my box, and it showed System.RtFieldInfo for example.)

Autres conseils

Debugger shows than testValue.GetType().GetField("MaxValue") returns RtFieldInfo which is derived from RuntimeFieldInfo which is derived from FieldInfo. So most likely this method was overriden in one of these classes. Most likely because there are different implementation of FieldInfo for runtime types and types from reflection-only loaded assemblies

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top