Dynamically Cast Map To Specific SObject
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<String,SObject> to Map<String,Account>
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 '<'.
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
add a comment |
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<String,SObject> to Map<String,Account>
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 '<'.
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
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
add a comment |
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<String,SObject> to Map<String,Account>
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 '<'.
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
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<String,SObject> to Map<String,Account>
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 '<'.
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
apex dynamic-apex
edited Dec 3 '18 at 17:03
Ryan Dinesman
asked Dec 3 '18 at 16:40
Ryan DinesmanRyan Dinesman
386
386
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
add a comment |
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
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 '18 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 '18 at 16:41
@battery.cord, thanks for the suggestion, post has been updated.
– Ryan Dinesman
Dec 3 '18 at 17:04
@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
@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
add a comment |
1 Answer
1
active
oldest
votes
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
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
add a comment |
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',
autoActivateHeartbeat: false,
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
add a comment |
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
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
add a comment |
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
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
edited Dec 3 '18 at 17:30
answered Dec 3 '18 at 17:11
Pranay JaiswalPranay Jaiswal
14.8k32653
14.8k32653
1
I was able to cast it to Account Map, Updated code for the same
– Pranay Jaiswal
Dec 3 '18 at 17:30
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
add a comment |
1
I was able to cast it to Account Map, Updated code for the same
– Pranay Jaiswal
Dec 3 '18 at 17:30
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
1
1
I was able to cast it to Account Map, Updated code for the same
– Pranay Jaiswal
Dec 3 '18 at 17:30
I was able to cast it to Account Map, Updated code for the same
– Pranay Jaiswal
Dec 3 '18 at 17:30
1
1
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
Makes sense, that works. Thank you very much!
– Ryan Dinesman
Dec 3 '18 at 17:32
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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