Dynamic References to Schema Details Using $ObjectType

The $ObjectType global variable provides access to a variety of schema information about the objects in your organization. Use it to reference names, labels, and data types of fields on an object, for example.
$ObjectType is a “deep” global variable, and offers the opportunity to use it in a “double dynamic” reference, like so:
$ObjectType[sObjectName].fields[fieldName].Type
Here’s an example that uses dynamic globals to provide a general object viewer. First, create a new controller (not extension) named DynamicObjectHandler:
public class DynamicObjectHandler {

    // This class acts as a controller for the DynamicObjectViewer component
    
    private String objType;
    private List<String> accessibleFields;

    public sObject obj { 
        get; 
        set {
	          setObjectType(value);
	          discoverAccessibleFields(value);
	          obj = reloadObjectWithAllFieldData();
        } 
    }
    
    // The sObject type as a string
    public String getObjectType() {
    	  return(this.objType);
    }
    public String setObjectType(sObject newObj) {
        this.objType = newObj.getSObjectType().getDescribe().getName();
        return(this.objType);
    }
    
    // List of accessible fields on the sObject
    public List<String> getAccessibleFields() {
     	return(this.accessibleFields);
    }
    
    private void discoverAccessibleFields(sObject newObj) {
        this.accessibleFields = new List<String>();
        Map<String, Schema.SobjectField> fields = 
            newObj.getSObjectType().getDescribe().fields.getMap();
        for (String s : fields.keySet()) {
            if ((s != 'Name') && (fields.get(s).getDescribe().isAccessible())) {
                this.accessibleFields.add(s);
            }
        }
    }
    
    private sObject reloadObjectWithAllFieldData() {
        String qid = ApexPages.currentPage().getParameters().get('id');
        String theQuery = 'SELECT ' + joinList(getAccessibleFields(), ', ') + 
                          ' FROM ' + getObjectType() + 
                          ' WHERE Id = :qid';
        return(Database.query(theQuery));    	
    }
    
    // Join an Apex List of fields into a SELECT fields list string
    private static String joinList(List<String> theList, String separator) {

        if (theList == null)   { return null; }
        if (separator == null) { separator = ''; }

        String joined = '';
        Boolean firstItem = true;
        for (String item : theList) {
            if(null != item) {
                if(firstItem){ firstItem = false; }
                else { joined += separator; }
                joined += item;
            }
        }
        return joined;
    }
}
There’s a number of things that are worth noting in this controller:
The next piece is a Visualforce component that displays schema information about an object, as well as the specific values of the record that is queried. Create a new Visualforce component named DynamicObjectViewer with the following code:
<apex:component controller="DynamicObjectHandler">
    <apex:attribute name="rec" type="sObject" required="true"
        description="The object to be displayed." assignTo="{!obj}"/>

    <apex:form >
    <apex:pageBlock title="{!objectType}">
        <apex:pageBlockSection title="Fields" columns="1">
            <apex:dataTable value="{!accessibleFields}" var="f">
                <apex:column >
                    <apex:facet name="header">Label</apex:facet>
                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Label}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">API Name</apex:facet>
                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Name}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Type</apex:facet>
                    <apex:outputText value="{!$ObjectType[objectType].fields[f].Type}"/>
                </apex:column>
                <apex:column >
                    <apex:facet name="header">Value</apex:facet>
                    <apex:outputText value="{!obj[f]}"/>
                </apex:column>
            </apex:dataTable>
        </apex:pageBlockSection>
        
        <apex:pageBlockSection columns="4">
            <apex:commandButton value="View"
                action="{!URLFOR($Action[objectType].View, obj.Id)}"/>
            <apex:commandButton value="Edit"
                action="{!URLFOR($Action[objectType].Edit, obj.Id)}"/>
            <apex:commandButton value="Clone"
                action="{!URLFOR($Action[objectType].Clone, obj.Id)}"/>
            <apex:commandButton value="Delete"
                action="{!URLFOR($Action[objectType].Delete, obj.Id)}"/>
        </apex:pageBlockSection>
    </apex:pageBlock>
    </apex:form>
    
</apex:component>
Notice the following:
Finally, the new component can be used to create any number of simple Visualforce pages that use the component to display a record detail and schema info page, such as these two pages:
<apex:page standardController="Account"> 
    <c:DynamicObjectViewer rec="{!account}"/>
</apex:page>
<apex:page standardController="Contact">
    <c:DynamicObjectViewer rec="{!contact}"/>
</apex:page>