递归查找所有DateTime对象

时间:2014-03-04 18:29:05

标签: c# reflection

在我的mvc项目中,我整理了一个动作过滤器,它接受模型,遍历对象图并修改所有日期时间对象。我当前的代码(在最后一个else块中)抛出了stackoverflow异常。

我的模型中的一个属性是具有导航属性的EF对象,这应该忽略没有值的属性或者是基元,字符串,枚举等。基本上任何没有子属性的类型日期时间。

    private void ProcessDateTimeProperties(object obj, ActionExecutedContext filterContext)
    {
        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<DateTime>))
            {
                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);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

你遇到的问题是循环参考。

您可以解决标记已检查的所有复杂对象的问题。像这样:


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);
            }
        }
    }

正如您所看到的,我将processedObjects可选参数添加到函数中以标记已传递给递归函数的对象。

当您调用该函数时,您不必传递此参数,它将在函数内部创建并递归传递。

希望这有帮助。