private TypeReflector(TypeReflector other)
 {
     _type       = other._type;
     _properties = other.Properties;
     IsArray     = other.IsArray;
     Name        = other.Name;
 }
        private static IEnumerable <TypeReflector> Navigate(Type type, string path, TypeReflector parentType)
        {
            Validate.NotNullOrEmptyOrWhiteSpace(path, nameof(path));

            path = path.Trim();

            var tokens            = path.Split('.');
            var token             = tokens.First();
            var arrayBracketIndex = token.IndexOf('[');
            var isArrayToken      = arrayBracketIndex > -1;

            if (isArrayToken)
            {
                token = token.Substring(0, arrayBracketIndex);
            }

            var properties = type.GetProperties()
                             .Where(pi => pi.CanRead && pi.CanWrite)
                             .ToDictionary(_ => _.Name, _ => _, StringComparer.OrdinalIgnoreCase);

            if (properties.TryGetValue(token, out var foundProperty))
            {
                var propertyType = foundProperty.PropertyType;
                var isArray      = false;
                if (propertyType.IsArray)
                {
                    propertyType = propertyType.GetElementType();
                    isArray      = true;
                }
                else if (propertyType.IsGenericType &&
                         propertyType.GetInterfaces().Any(x =>
                                                          x.IsGenericType &&
                                                          x.GetGenericTypeDefinition() == typeof(IEnumerable <>)))
                {
                    propertyType = propertyType.GetGenericArguments()[0];
                    isArray      = true;
                }

                var resolvedType = new TypeReflector(propertyType)
                {
                    IsArray = isArray, Parent = parentType, Name = token
                };

                yield return(resolvedType);

                if (tokens.Length > 1)
                {
                    foreach (var childType in Navigate(propertyType, string.Join(".", tokens.Skip(1)), resolvedType))
                    {
                        yield return(childType);
                    }
                }
            }
        }
        private void ReflectModelType()
        {
            if (_typeReflector != null)
            {
                return;
            }

            _typeReflector = TypeReflector.Create <T>();

            var idKey = _typeReflector.Properties.FirstOrDefault(_ => StringComparer.OrdinalIgnoreCase.Compare(_.Key, "id") == 0);

            if (idKey.Key == null)
            {
                idKey = _typeReflector.Properties.FirstOrDefault(_ => StringComparer.OrdinalIgnoreCase.Compare(_.Key, "uniqueid") == 0);
            }
            if (idKey.Key == null)
            {
                idKey = _typeReflector.Properties.FirstOrDefault(_ => StringComparer.OrdinalIgnoreCase.Compare(_.Key, "objectid") == 0);
            }

            if (idKey.Key != null &&
                _typeReflector.Properties[idKey.Key].PropertyType != typeof(int) &&
                _typeReflector.Properties[idKey.Key].PropertyType != typeof(Guid))
            {
                throw new InvalidOperationException("Id property must be of type Guid or Int32");
            }

            _idPropertyName = idKey.Key;
            if (_idPropertyName != null)
            {
                if (_typeReflector.Properties[_idPropertyName].PropertyType == typeof(int))
                {
                    _typeOfObjectId = ObjectIdType.Int;
                }
            }
        }