Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have

Schema.SObjectField field = MyObject__c.myField__c;
Schema.SObjectType objectType = getTypeOf(field);

how would getTypeOfField() need to look like for this to be true?

System.assertEquals(MyObject__c.SObjectType, objectType);
share|improve this question
    
Looks like I added a #duplicate of the unanswered salesforce.stackexchange.com/questions/32528/… – Robert Sösemann Apr 11 '14 at 13:28
2  
Looks like you added a #duplicate of the answered salesforce.stackexchange.com/q/29911/... ;-) it's a no-go even with getReferenceTo() – bigassforce Apr 11 '14 at 13:49
    
I think in 2 years someone might have found a solution to this. So please don't close ;-) – Robert Sösemann Apr 11 '14 at 14:01
1  
I agree with @user320 it's a no go, just been racking my brain on this one also, the methods of SObjectFieldDescribe just don't provide any indiction, best i could suggest is if you know your always going to be passing a field from a known subset of custom objects is to build a map (via the fields.getMap()) internally and store it statically. – Andrew Fawcett Apr 11 '14 at 15:23
3  
Does it have to be a Schema.SObjectField? If you could start passing fieldsets around you might gain some flexibility (admin able to modify the page without the help of a developer) and the FieldSet class does have the getSobjectType(): salesforce.com/us/developer/docs/apexcode/Content/… – eyescream Apr 11 '14 at 20:56

I may be missing the boat here but why not a method based on the following?

// Build a map of hashcodes for each fieldDescribe taken from Schema Global Describe
Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();
Map<Integer,Schema.SObjectType> fldHashCodeToSObjectTypeMap = new map<Integer,Schema.SObjectType>();

for (String sobjname: gd.keySet()) {
    for (Schema.SObjectField sobjField : gd.get(sObjName).getDescribe().fields.getMap().values())
        fldHashCodeToSObjectTypeMap.put(((Object) sObjField).hashCode(),gd.get(sobjName));

}

// Then compare your sobjectField in hand by hashing it and then looking up into the map
Schema.SObjectField field0 = Account.Industry; 
Integer field0Hash = ((Object) field0).hashCode();
Schema.SObjectField field1 = Opportunity.CloseDate; 
Integer field1Hash = ((Object) field1).hashCode();

System.debug(LoggingLevel.INFO,'field0 belongs to sobject:' + fldHashCodeToSObjectTypeMap.get(field0Hash)); 
System.debug(LoggingLevel.INFO,'field1 belongs to sobject:' + fldHashCodeToSObjectTypeMap.get(field1Hash));

Debug output yields:

17:58:06.113 (1113461278)|USER_DEBUG|[16]|INFO|field0 belongs to sobject:Account
17:58:06.113 (1113547114)|USER_DEBUG|[17]|INFO|field1 belongs to sobject:Opportunity

Your Util.getType(someSobjectField) method would simply do

fldHashCodeToSObjectTypeMap.get((Object) someSobjectField).hashCode());

on some static variable instantiation of fldHashCodeToSObjectTypeMap

share|improve this answer
    
hashCode func is an interesting angle - looks good! – bigassforce Jan 14 at 2:24
    
@bigassforce : this is what happens when one reads too many SFSE answers from smarter folks than me; odd ideas show up in my brain – cropredy Jan 14 at 2:28
    
I think I don't really like this because what you do is not asking a encapsulated system for an answer bu store all possible answers in a map before and than just retrieve them. – Robert Sösemann Jan 15 at 15:34
    
oh well. At least your 50 pt incentive inspired me to learn something new. – cropredy Jan 15 at 16:02
1  
Sure @crop1645 thanks for sharing your idea. It's better than leaving it unsolved. But actually I expected some Salesforce internals to tell me there is an undocumented method getSObjectType() on SObjectField ;-) – Robert Sösemann Jan 15 at 18:58

While I really hope there is an easier way to achieve this, the Tooling API might be one candidate.

You can interrogate the Salesforce Tooling API with an Apex library or just use the code below by itself:

  1. First specify your field name:

    //choose your field name (without suffix!)
    String fieldName = yourField.getDescribe().getName().substringBefore('__c');
    System.debug(fieldName);
    

    'Status'

  2. Then obtain the Custom Object Id (eg 01I...) or Table Enum (eg Account) which it lives on:

    String query = 'SELECT TableEnumOrId From CustomField WHERE DeveloperName = \'' + fieldName + '\'';
    String endpoint = Url.getSalesforceBaseUrl().toExternalForm();
    endpoint += '/services/data/v29.0/tooling/query/?q=';
    endpoint += EncodingUtil.urlEncode(query, 'UTF-8');
    
    HttpRequest request = new HttpRequest();
    request.setMethod('GET');
    request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
    request.setEndpoint(endpoint);
    
    HttpResponse response = new Http().send(request);
    String tableEnumOrId = response.getBody().substringAfter('"TableEnumOrId":"').substringBefore('"');
    
    System.debug(tableEnumOrId);
    

    '01Ib0000000CM8TEAW'

  3. Finally, you can pull the API / Developer Name off the Custom Object definition itself:

    query = 'SELECT DeveloperName From CustomObject Where Id = \'' + tableEnumOrId + '\'';
    endpoint = Url.getSalesforceBaseUrl().toExternalForm();
    endpoint += '/services/data/v29.0/tooling/query/?q=';
    endpoint += EncodingUtil.urlEncode(query, 'UTF-8');
    
    request = new HttpRequest();
    request.setMethod('GET');
    request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
    request.setEndpoint(endpoint);
    
    response = new Http().send(request);
    System.debug(response.getBody());
    String customObjectName = response.getBody().substringAfter('"FullName":"').substringBefore('"');
    
    System.debug(customObjectName);
    

    'Schematic'

  4. Use Type.forName to get at your desired SObject, SObjectType, or DescribeSObjectResult:

    Type reflector = Type.forName('Invoice__c');
    SObject obj = (SObject)reflector.newInstance();
    SObjectType objectType = obj.getSObjectType();
    //now you can do objectType.getDescribe etc...
    

There are a number of caveats which would need serious 'hardening':

  • you may need to truncate or append the __c as necessary in the Tooling API queries
  • in managed context you will need to play with the namespace prefix.
  • gonna be tricky if you have multiple fields with the same name!
share|improve this answer
3  
Just wondering how this would work if i had the same field name on multiple custom objects? e.g. Total on object A and object B? – Andrew Fawcett Apr 11 '14 at 15:00
    
My code probably won't work :( definitely a tricky area, have added that to the list of caveats! Thanks @AndrewFawcett – bigassforce Apr 11 '14 at 15:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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