3

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?

3
  • 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. Dec 3, 2018 at 16:41
  • @battery.cord, thanks for the suggestion, post has been updated. Dec 3, 2018 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. Dec 3, 2018 at 17:08

1 Answer 1

9

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
  • 1
    I was able to cast it to Account Map, Updated code for the same Dec 3, 2018 at 17:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .