Dynamically Cast Map To Specific SObject











up vote
1
down vote

favorite












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?










share|improve this question




















  • 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 at 16:41










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















up vote
1
down vote

favorite












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?










share|improve this question




















  • 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 at 16:41










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













up vote
1
down vote

favorite









up vote
1
down vote

favorite











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?










share|improve this question















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?







apex dynamic-apex






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 3 at 17:03

























asked Dec 3 at 16:40









Ryan Dinesman

285




285








  • 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 at 16:41










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














  • 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 at 16:41










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








1




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 at 16:41




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 at 16:41












@battery.cord, thanks for the suggestion, post has been updated.
– Ryan Dinesman
Dec 3 at 17:04




@battery.cord, thanks for the suggestion, post has been updated.
– Ryan Dinesman
Dec 3 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 at 17:08




@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 at 17:08










1 Answer
1






active

oldest

votes

















up vote
5
down vote



accepted










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






share|improve this answer



















  • 1




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






  • 1




    Makes sense, that works. Thank you very much!
    – Ryan Dinesman
    Dec 3 at 17:32











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f241250%2fdynamically-cast-mapstring-sobject-to-specific-sobject%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
5
down vote



accepted










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






share|improve this answer



















  • 1




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






  • 1




    Makes sense, that works. Thank you very much!
    – Ryan Dinesman
    Dec 3 at 17:32















up vote
5
down vote



accepted










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






share|improve this answer



















  • 1




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






  • 1




    Makes sense, that works. Thank you very much!
    – Ryan Dinesman
    Dec 3 at 17:32













up vote
5
down vote



accepted







up vote
5
down vote



accepted






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






share|improve this answer














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







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 3 at 17:30

























answered Dec 3 at 17:11









Pranay Jaiswal

12.5k32251




12.5k32251








  • 1




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






  • 1




    Makes sense, that works. Thank you very much!
    – Ryan Dinesman
    Dec 3 at 17:32














  • 1




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






  • 1




    Makes sense, that works. Thank you very much!
    – Ryan Dinesman
    Dec 3 at 17:32








1




1




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




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




1




1




Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 at 17:32




Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 at 17:32


















draft saved

draft discarded




















































Thanks for contributing an answer to Salesforce Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f241250%2fdynamically-cast-mapstring-sobject-to-specific-sobject%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

mysqli_query(): Empty query in /home/lucindabrummitt/public_html/blog/wp-includes/wp-db.php on line 1924

How to change which sound is reproduced for terminal bell?

Can I use Tabulator js library in my java Spring + Thymeleaf project?