Crazy idea... Create a collection of Apex classes. One for every API version you are interested in getting metadata for. The sole purpose of that class is to call Schema.sObjectType.getDescribe()
and return the result.
Very rough prototype:
public interface DescribeApiVersioned {
Schema.DescribeSObjectResult getDescribe(Schema.sObjectType sObjectType);
}
public class DescribeApiVersioned42 implements DescribeApiVersioned {
public Schema.DescribeSObjectResult getDescribe(Schema.sObjectType sObjectType) {
Schema.DescribeSObjectResult v42 = sObjectType.getDescribe();
System.debug('Number of fields v42 : ' + v42.fields.getMap().size());
return v42;
}
}
public class DescribeApiVersioned38 implements DescribeApiVersioned {
public Schema.DescribeSObjectResult getDescribe(Schema.sObjectType sObjectType) {
Schema.DescribeSObjectResult v38 = sObjectType.getDescribe();
System.debug('Number of fields v38 : ' + v38.fields.getMap().size());
return v38;
}
}
Then testing it with anonymous Apex from v42.0:
Schema.sObjectType t = ContentDocument.sObjectType;
DescribeApiVersioned v42 = new DescribeApiVersioned42();
DescribeApiVersioned v38 = new DescribeApiVersioned38();
Schema.DescribeSObjectResult cd42 = v42.getDescribe(t);
Schema.DescribeSObjectResult cd38 = v38.getDescribe(t);
System.debug('v42: ' + cd42.fields.getMap().size());
System.debug('v38: ' + cd38.fields.getMap().size());
Result:
13:08:15.2 (11189280)|USER_DEBUG|[4]|DEBUG|Number of fields v42 : 25
13:08:15.2 (11935260)|USER_DEBUG|[4]|DEBUG|Number of fields v38 : 24
13:08:15.2 (12562021)|USER_DEBUG|[8]|DEBUG|v42: 25
13:08:15.2 (12749702)|USER_DEBUG|[9]|DEBUG|v38: 25
Well dang. The v38.0 bounced back to 25 in the anonymous Apex. It appears Schema.DescribeSObjectResult
alters its results depending on the API version of the class interacting with it. Not the API version of the class where it was called. All is not lost though. You would just need to push the code that builds the field set up from the describe results into the versioned class.