Below is what I came up with:
/// <summary>
/// Gets the field value from the IObject. Checks for coded
/// value domains, subtypes, or just the plain field value.
/// </summary>
/// <param name="obj">ESRI IObject</param>
/// <param name="fieldIndex">Field index for the IObject.Fields.Field</param>
/// <returns></returns>
internal static object ReadFieldValue(IObject obj, int fieldIndex, bool ignoreDescription = false)
{
object fieldValue = null;
if (obj != null && fieldIndex > -1)
{
/// Default to the field value first,
/// overwrite it if a subtype or domain
/// is found.
fieldValue = obj.Value[fieldIndex];
if (fieldValue != DBNull.Value && ignoreDescription == false)
{
ISubtypes subtypes = obj.Class as ISubtypes;
IRowSubtypes rowSubtypes = obj as IRowSubtypes;
IField2 field = obj.Fields.Field[fieldIndex] as IField2;
// Set the appropriate domain based on the subtype if a subtype exists.
IDomain domain = null;
if (field != null)
{
if (subtypes != null && subtypes.SubtypeFieldIndex > -1)
{
domain = subtypes.get_Domain(rowSubtypes.SubtypeCode, field.Name);
}
else
{
domain = field.Domain;
}
}
// Check for a subtype field first
if (subtypes != null && rowSubtypes != null && subtypes.SubtypeFieldIndex == fieldIndex)
fieldValue = subtypes.get_SubtypeName(rowSubtypes.SubtypeCode);
// If it is not a subtype field, check for a domain field
else if (domain != null)
{
ICodedValueDomain2 cvDomain = domain as ICodedValueDomain2;
if (cvDomain != null)
{
for (int i = 0; i < cvDomain.CodeCount; i++)
{
if (cvDomain.get_Value(i).Equals(fieldValue))
{
fieldValue = cvDomain.get_Name(i);
break;
}
}
}
}
}
}
return fieldValue;
}