public DeepTracker Create()
        {
            CheckCreated();

            //First step optimization - collapse well known include filters
            var includeList = _includeList.ToList();

            _includeList.Clear();

            var includeRouteFilters = includeList.Enumerate <IncludeRoute>().ToList();

            if (includeRouteFilters.Any())
            {
                _includeList.Add(new IncludeRoute(includeRouteFilters.SelectMany(f => f.Routes).Distinct().ToArray()));
                includeList = includeList.Except(includeRouteFilters).ToList();
            }

            var includeObjectPropertyFilters = includeList.Enumerate <IncludeObjectProperty>().ToList();

            if (includeObjectPropertyFilters.Any())
            {
                var collapsedPairs = includeObjectPropertyFilters
                                     .SelectMany(f => f.ObjectProperties.SelectMany(g => g.Select(property => new KeyValuePair <Type, string>(g.Key, property))))
                                     .DistinctBy(p => p.Key.GetHash().MergeHash(p.Value.GetHash()))
                                     .ToArray();

                _includeList.Add(new IncludeObjectProperty(collapsedPairs));
                includeList = includeList.Except(includeObjectPropertyFilters).ToList();
            }

            _includeList.AddRange(includeList);

            //First step optimization - collapse well known exclude filters
            var excludeList = _excludeList.ToList();

            _excludeList.Clear();

            var excludeRouteFilters = excludeList.Enumerate <ExcludeRoute>().ToList();

            if (excludeRouteFilters.Any())
            {
                _excludeList.Add(new ExcludeRoute(excludeRouteFilters.SelectMany(f => f.Routes).Distinct().ToArray()));
                excludeList = excludeList.Except(excludeRouteFilters).ToList();
            }

            var excludeSourceTypeWithDerivedFilters = excludeList.Enumerate <ExcludeSourceType>().Where(f => f.Derived).ToList();

            if (excludeSourceTypeWithDerivedFilters.Any())
            {
                _excludeList.Add(new ExcludeSourceType(true, excludeSourceTypeWithDerivedFilters.SelectMany(f => f.Types).Distinct().ToArray()));
                excludeList = excludeList.Except(excludeSourceTypeWithDerivedFilters).ToList();
            }

            var excludeSourceTypeWithNonDerivedFilters = excludeList.Enumerate <ExcludeSourceType>().Where(f => !f.Derived).ToList();

            if (excludeSourceTypeWithNonDerivedFilters.Any())
            {
                _excludeList.Add(new ExcludeSourceType(false, excludeSourceTypeWithNonDerivedFilters.SelectMany(f => f.Types).Distinct().ToArray()));
                excludeList = excludeList.Except(excludeSourceTypeWithNonDerivedFilters).ToList();
            }

            var excludePropertyTypeWithDerivedFilters = excludeList.Enumerate <ExcludePropertyType>().Where(f => f.Derived).ToList();

            if (excludePropertyTypeWithDerivedFilters.Any())
            {
                _excludeList.Add(new ExcludePropertyType(true, excludePropertyTypeWithDerivedFilters.SelectMany(f => f.Types).Distinct().ToArray()));
                excludeList = excludeList.Except(excludePropertyTypeWithDerivedFilters).ToList();
            }

            var excludePropertyTypeWithNonDerivedFilters = excludeList.Enumerate <ExcludePropertyType>().Where(f => !f.Derived).ToList();

            if (excludePropertyTypeWithNonDerivedFilters.Any())
            {
                _excludeList.Add(new ExcludePropertyType(false, excludePropertyTypeWithNonDerivedFilters.SelectMany(f => f.Types).Distinct().ToArray()));
                excludeList = excludeList.Except(excludePropertyTypeWithNonDerivedFilters).ToList();
            }

            var excludeObjectPropertyFilters = excludeList.Enumerate <ExcludeObjectProperty>().ToList();

            if (excludeObjectPropertyFilters.Any())
            {
                var collapsedPairs = excludeObjectPropertyFilters
                                     .SelectMany(f => f.ObjectProperties.SelectMany(g => g.Select(property => new KeyValuePair <Type, string>(g.Key, property))))
                                     .DistinctBy(p => p.Key.GetHash().MergeHash(p.Value.GetHash()))
                                     .ToArray();

                _excludeList.Add(new ExcludeObjectProperty(collapsedPairs));
                excludeList = excludeList.Except(excludeObjectPropertyFilters).ToList();
            }

            _excludeList.AddRange(excludeList);
            _excludeList.Add(new ExcludeByAttribute());

            var result = new DeepTracker(this, _source);

            _source    = null;
            _isCreated = true;
            return(result);
        }
 public void Raise(DeepTracker deepTracker, RouteEventArgs args)
 {
     _subscriptionStorage.Raise(deepTracker, args);
 }