3

I have a class from a third-party library with a read-only property called Name. Here is the code for the class:

public class Person
{
    public string Name {get;}
}

I want to set the value of the Name property using reflection or another suitable method, but I don't know how the property is implemented. Specifically, I don't know if it has a backing field like this:

private string m_name;

or if it is implemented like this:

public string Name {get; private set;}

How can I set the value of the Name property in this situation?

Vahid
  • 5,144
  • 13
  • 70
  • 146
  • @maccettura https://stackoverflow.com/questions/934930/can-i-change-a-private-readonly-field-in-c-sharp-using-reflection – Vahid Nov 14 '17 at 22:02
  • Huh, today I learned... – maccettura Nov 14 '17 at 22:03
  • @maccettura me too! Actually! – Vahid Nov 14 '17 at 22:03
  • @itsme86 This is different. I do not know the backing field here! – Vahid Nov 14 '17 at 22:05
  • Regarding your actual question, I think this will be impossible until you know the backing field name. You could try to decompile the dll using DotNetPeek or something? – maccettura Nov 14 '17 at 22:07
  • @itsme86, this is not a duplicate of that question. OP _does not_ know the name of the private variable. – maccettura Nov 14 '17 at 22:08
  • @maccettura Thanks. Yes you are right. I think that is the only way. – Vahid Nov 14 '17 at 22:09
  • Doesn't it have a `SetName()` method or something like this? Try using the dot navigator – ceferrari Nov 14 '17 at 22:13
  • 1
    @Vahid...if its an auto-implemented property then the instance variable for Name would be name. – Chris Catignani Nov 14 '17 at 22:20
  • 1
    @ChrisCatignani With the current builds of Roslyn, the backing field name is `k__BackingField`. – yaakov Nov 14 '17 at 22:22
  • 1
    `Mono.Reflection` has an extension method `GetBackingField()` for `PropertyInfo` which returns `FieldInfo`. This only works for auto-properties. Since you said it's a 3rd-party library, there's a good chance it's not an auto-property and you're out of luck. – Mr Anderson Nov 14 '17 at 22:24
  • Thanks I will give it a try tomorrow at work! ,) – Vahid Nov 14 '17 at 22:32
  • 1
    There's also the possibility that it does not _have_ a backing field - that the name is generated in the getter somehow. You _could_ decompile the DLL and look at the getter's code, but I do not know of at automated way to do that. – D Stanley Nov 14 '17 at 22:41

1 Answers1

6

You need to obtain a FieldInfo instance for the property's backing field and call the SetValue() method.

The Mono.Reflection library (available in Package Manager) will help you find the backing field.

If the Property is an auto-property, you can call the GetBackingField() extension method on the PropertyInfo instance.

Otherwise, you'll have to disassemble the IL of the MethodInfo of the getter like this:

var instructions = yourProp.GetGetMethod().GetInstructions();

This will give you a list of the method's IL instructions. If they look like this:

Ldarg0
Ldfld    (Backing Field)
Ret

Then the 2nd Instruction will give you the backing field. In code:

if (instructions.Count == 3 && instructions[0].OpCode == OpCodes.Ldarg_0 && instructions[1].OpCode == OpCodes.Ldfld && instructions[2].OpCode == OpCodes.Ret)
{
    FieldInfo backingField = (FieldInfo)instructions[1].Operand;
}

Otherwise, the property is probably computed and has no backing field.

Mr Anderson
  • 2,200
  • 13
  • 23