[SalesForce] Dynamic invocation (or emulation) of the hierarchy custom setting getInstance() method

I have a requirement to avoid any compile-time dependency on a managed package. Dynamic SOQL, SObjectType and SObject allow me to do this cleanly for normal objects.

But now I need to access a public hierarchy custom setting from the managed package. With compile-time dependency this would work:

ns__CustomSetting__c setting = ns__CustomSetting__c.getInstance();

But there does not appear to be a dynamic alternative API; methods like getInstance() are not present on SObject. Or have I missed something?

Is the only approach available to use dynamic SOQL to query the various rows of the hierarchy and emulate the semantics of getInstance() in Apex code?

Best Answer

You can access custom settings dynamically through a query. Unfortunately, this means that you'll have to burn a query and at least one query row (and up to 3). First, you'll get the user's organization ID, profile ID, and user ID, then perform a query like: SELECT Id, SetupOwnerId FROM CustomSetting__c WHERE SetupOwnerId IN (:userId, :profileId, :orgId). Then, you have to go through each field of each returned row (if any), and override higher level settings with lower level settings.

Map<SObjectType, Setting__c> settings = new Map<SobjectType, Setting__c>();
for(Setting__c record: [SELECT Id, SetupOwnerId... FROM Setting__c WHERE ...])
    settings.put(record.setupownerid.getsobjecttype(), record);

if(settings.containskey(organization.sobjecttype)) {
    ...
}
if(settings.containskey(profile.sobjecttype)) {
    ...
}
if(settings.containskey(user.sobjecttype)) {
    ...
}

There's no other way to access those settings. Also, you can't access protected settings outside the package.