1

We realized that often time in our code we're iterating through a list of SObjects and creating a map of String to SObject. To try and reduce how many times we're repeating this code, we were going to add it to a generic SObjectDomain that specific SObject domains extend.

Map<String, SObject> createStringFieldToSObjectsMap(String fieldName, List<SObject> sobjects){
    Map<String, SObject> sobjectMap = new Map<String, SObject>();
    for(SObject currentSObject : sobjects){
        sobjectMap.put(currentSObject.get(fieldName),currentSObject);
    }
    return sobjectMap;
}

The problem we're running into is that it's difficult to convert a generic SObject map into a specific SObject map. I tried just casting the generic map as the specific map, but ran into the following error:

Map<String, SObject> genericMap = new Map<String, SObject>();
Map<String, Account> accountMap = (Map<String, Account>) genericMap;

System.TypeException: Invalid conversion from runtime type Map&lt;String,SObject&gt; to Map&lt;String,Account&gt;

I also tried to declare the map with a dynamic SObject type in the following ways, but each time ran into an error saying that it was an invalid type.

Map<String, Account.SObjectType> accountMap = new Map<String, Account.SObjectType>();
Map<String, Account.SObjectType> accountMap = new Map<String, SObject>();
Map<String, Schema.SObjectType.Account> accountMap;

I also tried to use method like getSObjectType(), but I kept getting the following error:

Map<String, Account.getSObjectType()> accountMap = new Map<String, Account.getSObjectType()>();
Map<String, Account.getSObjectType()> accountMap = new Map<String, SObject>();
//Unexpected token '&lt;'.

I found a lot of posts stating that dynamically determining SObject type wasn't supported, but these posts were at least 4 years old and a lot has changed in that time. Does anyone know if what we're trying to do is possible?

  • 1
    A code sample would help a lot here. It doesnt matter if it fails, just put the compile/runtime errors in the code as a comment. – battery.cord Dec 3 '18 at 16:41
  • @battery.cord, thanks for the suggestion, post has been updated. – Ryan Dinesman Dec 3 '18 at 17:04
  • @gNerb, I thought of that as well, but it just seems strange for a specific SObject domain to return a generic SObject. If you're calling AccountDomain.getMap, you'd expect it to return a map of String to Account, not String to SObject. I'm not sure if I'm being too nitpicky there. – Ryan Dinesman Dec 3 '18 at 17:08
6

I am not pretty sure why you wanna do it. You can dynamically instantiate Map using Type.newInstance(), Probably that's what you need?

 public static Map<String, SObject> createStringFieldToSObjectsMap(String fieldName, List<SObject> sobjects){
        String soBjectTypeString = String.valueOf(sobjects[0].getSObjectType());
        Type t= Type.forName('Map<String,'+soBjectTypeString+'>');  
        Map<String,Sobject> sobjectMap =(Map<String,Sobject>)t.newInstance();
        for(SObject currentSObject : sobjects){
            sobjectMap.put(String.valueOf(currentSObject.get(fieldName)),currentSObject);
        }
        return sobjectMap;   



}

Then to test

List<Sobject> sobjectList  =[Select Id from Account ];

System.debug(MyUtil.createStringFieldToSObjectsMap('Id',sobjectList) instanceof Map<String,Account>); //Returns true

Cast to AccountMap:

Map<String,Account> accMap =(Map<String,Account> ) MyUtil.createStringFieldToSObjectsMap('Id',sobjectList);

Src: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_type.htm

  • 1
    I was able to cast it to Account Map, Updated code for the same – Pranay Jaiswal Dec 3 '18 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.