The problem you have is circular reference.
You can solve your problem marking all the complex objects you already checked. like this:
private void ProcessDateTimeProperties(object obj, ActionExecutedContext filterContext, HashSet<object> processedObjects = null)
{
if (processedObjects == null)
processedObjects = new HashSet<object>();
if (processObjects.Contains(obj))
return;
processedObjects.Add(obj);
var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties)
{
var t = property.PropertyType;
if (t.IsPrimitive || t == typeof(string) || t == typeof(Enum))
continue;
var p = property;
if (p.PropertyType == typeof(DateTime))
{
var date = (DateTime)p.GetValue(obj, null);
date.AddMinutes((int)filterContext.HttpContext.Cache["offset"]);
p.SetValue(obj, date, null);
}
// Same check for nullable DateTime.
else if (p.PropertyType == typeof(Nullable))
{
var date = (DateTime?)p.GetValue(obj, null);
if (!date.HasValue) continue; ;
date.Value.AddMinutes((int)filterContext.HttpContext.Cache["offset"]);
p.SetValue(obj, date, null);
}
else
{
var v = property.GetValue(obj, null);
if (v != null)
ProcessDateTimeProperties(v, filterContext, processedObjects);
}
}
}
As you can see I'm adding the processedObjects
optional parameter to the function to mark the objects that were already passed to the recursive function.
When you call the function you don't have to pass this parameter, it will be created inside the function and passed recursively.
Hope this helps.