[SalesForce] Is it possible to dynamically set properties of an `Object` using Apex

Background

I would like to be able to dynamically set properties of an Object (not SObject).

Given this class:

public class Invoice {
    public String Ref { get; set; }
}

I would like to be able to do this:

Invoice inv = new Invoice();
inv.put('Ref', 'REF123');

But when I do Execute Anonymous Apex with above code, I this error:

ERROR: Compilation failed.
! ERROR: Line: 3, Column: 12
! Method does not exist or incorrect signature: void put(String, String)
! from the type Invoice
ERROR: Execution failed.

Question

  1. Is it possible to dynamically set properties of an Object (not SObject) using Apex?
  2. How would I dynamically set a property of an Object using Apex?

Best Answer

For some isolated cases - yours is one of them - there is this (ab)use of the serialize methods:

Invoice inv = (Invoice) JSON.deserialize(JSON.serialize(new Map<<String, Object>{
    'Ref' => 'REF123'
})), Invoice.class);

Here, the capability of JSON.deserialize to create an instance of the specified type and set the properties of the instance is being used.

But in general, Apex is missing the map-like behavior for objects or a reflection API.