A Tooling API Solution
I've been able to try out a hunch I've had since I noticed CustomField support in the Tooling API and have worked up a means to dynamically query the Custom Field Id's via the supported Salesforce Tooling API. My fresh from the press blog entry here goes into more details, though here is a code sample taken from the accompanying GitHub repo.
// Constructs the Tooling API wrapper (default constructor uses user session Id)
ToolingAPI toolingAPI = new ToolingAPI();
// Query CustomObject object by DeveloperName (note no __c suffix required)
List<ToolingAPI.CustomObject> customObjects =
toolingAPI.queryCustomObject('DeveloperName = \'Test\'').records;
// Query CustomField object by TableEnumOrId (use CustomObject Id not name for Custom Objects)
ToolingAPI.CustomObject customObject = customObjects[0];
Id customObjectId = customObject.Id;
List<ToolingAPI.CustomField> customFields =
toolingAPI.queryCustomField('TableEnumOrId = \'' + customObjectId + '\'').records;
// Dump field names (reapply the __c suffix) and their Id's
System.debug(customObject.DeveloperName + '__c : ' + customObject.Id);
for(ToolingAPI.CustomField customField : customFields)
System.debug(
customObject.DeveloperName + '__c.' +
customField.DeveloperName + '__c : ' +
customField.Id);
This results in ....
00:27:38.845 (845882069)|USER_DEBUG|[45]|DEBUG|Test__c : 01IG00000021cXoMAI
00:27:38.846 (846249350)|USER_DEBUG|[47]|DEBUG|Test__c.A_Number__c : 00NG0000009Y0I9MAK
00:27:38.846 (846305290)|USER_DEBUG|[47]|DEBUG|Test_c.Colours_c : 00NG0000009prwyMAA
00:27:38.846 (846328856)|USER_DEBUG|[47]|DEBUG|Test_c.Date_c : 00NG0000009BrnxMAC
00:27:38.846 (846513094)|USER_DEBUG|[47]|DEBUG|Test_c.Message_c : 00NG0000009Y0IOMA0
00:27:38.846 (846535746)|USER_DEBUG|[47]|DEBUG|Test_c.MultiPick_c : 00NG000000AcULrMAN
00:27:38.846 (846558753)|USER_DEBUG|[47]|DEBUG|Test_c.MyCheckbox_c : 00NG0000009Y5C8MAK
00:27:38.846 (846741056)|USER_DEBUG|[47]|DEBUG|Test_c.RichText_c : 00NG0000009XaRJMA0
00:27:38.846 (846816183)|USER_DEBUG|[47]|DEBUG|Test_c.Text_c : 00NG0000009prxwMAA
Summary. There CustomField object has a little amount of queryable fields this way, basically DeveloperName, TableEnumOrId (custom object Id or standard object name) and NamespacePrefix. These should allow you to dynamically query for most use cases. Keep in mind the solution uses a callout from Apex to the Tooling API (REST version), so you will need to have a Remote Site setting for the Tooling API end point added to the org.