0

I have a rather simple Trigger. When fired it determines its own type and calls an appropriate function in Trigger handler class.

trigger Project_Trigger on Acme_Project__c (before insert, after insert, before update) {
    if (Trigger.isBefore) {
        if (Trigger.isInsert) {  
            ProjectHandler.projectBeforeInsert(Trigger.new);
        }
        ...
    }
    ...
}

Trigger handler class takes Trigger.old/Trigger.new and performs all required logic.

public class ProjectHandler {
    public static void projectBeforeInsert(List<Acme_Project__c> newProjects) {
        ...
    }
}

I would like to make the handler class work for many different Custom Objects, not only for Acme_Projects__c. In fact I already have those Custom Objects and I can just clone the class and find/replace 'Acme' with, for instance, 'Some_Other_Client', but that seems too repetitive.

My idea is to create an intermediary Custom Object, like Clipboard_Project__c, and use it to populate with Trigger.old/Trigger.new values, perform class handler methods on instances of that Custom Object, and then return everything back to trigger to do final DML operations...

In the Trigger -

Clipboard_Project__c[] newProjects;

for (Acme_Project__c p : Trigger.new) {
    Clipboard_Project__c one = new Clipboard_Project__c(
        Id = p.Id,
        Field_1__c = p.Field_1__c,
        ...);
    newProjects.add(one);
}

ProjectHandler.projectBeforeInsert(newProjects);

//some code that puts newProjects back into Trigger.new

delete(newProjects);

Is this a viable approach? How do I put newProject contents back into Trigger.new (as far as I understand that's the only way to make Custom Object instances update)?

1 Answer 1

4

Apex has support for generic sObjects. You can do pretty much anything with a generic sobject that you could do with a specific sObject type (get/set fields, dml operations, etc.) So you could write your generic handler as follows:

public class myTriggerHandler {
    public static void BeforeInsertHandler(List<Sobject> newRecords) {
        ...
    }
}

There is no reason to pass anything back to the triggers as you can perform everything in the trigger handler. The best practice is to have a simple trigger that delegates all the actual work to a trigger handler. If you have slightly different logic for the different types of sObjects:

public class myTriggerHelper {
    public static void doGenericLogic(List<Sobject> newRecords) {
        ...
    }
}

public class ProjectHandler {
    public static void projectBeforeInsert(List<Acme_Project__c> newProjects) {
        myTriggerHelper.doGenericLogic(newProjects);
        ...
    }
}
3
  • Thanks grigriforce, SObject type seems to work. However, I get an error when trying to perform logic in the handler - for (SObject p : newProjects) { if (p.Stage__c != 'Complete') { String type = p.Project_Type__c; ... } }. The erro is 'Field expression not allowed for generic SObject'.
    – dfo
    Jan 21, 2013 at 13:35
  • you have to access them dynamically since it doesn't know what fields exist on the Sobject (or cast to the appropriate sObject type). p.get('Stage__c')..type = (String) p.get('Project_Type__c) Jan 21, 2013 at 14:45
  • As @grigriforce mentioned, you've got to take the generic sObject type and determine it's concrete type in order to access the fields. Inside the helper method you can use the sObject describe info to determine the object type and act accordingly. if (yourObject.getsObjectType() == Acme_Project__c.sObjectType) { /* cast each item to the Acme_Project__c class and perform logic */ Acme_Project__c aproject = (Acme_Project__c)listItem; aproject.Project_Type__c = ...; }
    – Mark Pond
    Jan 22, 2013 at 16:29

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.