protected TResult ExecuteSingleObjectQueryWithFallback <TResult>(Func <TSession, TResult> query, Func <TResult, List <Tuple <string, KeyType> > > getAdditionalKeys = null, IEnumerable <PropertyDefinition> properties = null) where TResult : ADRawEntry, new()
        {
            ArgumentValidator.ThrowIfNull("query", query);
            if (!Configuration.IsCacheEnabled(typeof(TResult)))
            {
                return(query(this.GetSession()));
            }
            Stopwatch stopwatch = Stopwatch.StartNew();

            CachePerformanceTracker.StartLogging();
            CompositeDirectorySession <TSession> .TraceState traceState = CompositeDirectorySession <TSession> .TraceState.None;
            CacheMode          cacheModeForCurrentProcess = Configuration.GetCacheModeForCurrentProcess();
            double             num                = -1.0;
            double             num2               = -1.0;
            double             num3               = -1.0;
            double             num4               = -1.0;
            TResult            tresult            = default(TResult);
            string             text               = string.Empty;
            Guid               guid               = Guid.Empty;
            ADCacheResultState adcacheResultState = ADCacheResultState.Succeed;
            bool               flag               = true;
            int num5 = 0;

            try
            {
                Stopwatch stopwatch2 = null;
                ADObject  adobject   = null;
                try
                {
                    TSession session = this.GetSession();
                    if (session.ActivityScope != null)
                    {
                        TSession session2 = this.GetSession();
                        if (session2.ActivityScope.Status == ActivityContextStatus.ActivityStarted)
                        {
                            TSession session3 = this.GetSession();
                            guid = session3.ActivityScope.ActivityId;
                        }
                    }
                    if (!this.CacheSessionForDeletingOnly && (CacheMode.Read & cacheModeForCurrentProcess) != CacheMode.Disabled)
                    {
                        TSession session4 = this.GetSession();
                        if (!session4.SessionSettings.IncludeSoftDeletedObjectLinks)
                        {
                            if (properties != null || !typeof(TResult).Equals(typeof(ADRawEntry)))
                            {
                                traceState |= CompositeDirectorySession <TSession> .TraceState.CacheRead;
                                stopwatch2  = Stopwatch.StartNew();
                                tresult     = query(this.GetCacheSession());
                                CacheDirectorySession cacheDirectorySession = this.GetCacheSession() as CacheDirectorySession;
                                if (cacheDirectorySession != null)
                                {
                                    adcacheResultState = cacheDirectorySession.ResultState;
                                    flag = cacheDirectorySession.IsNewProxyObject;
                                    num5 = cacheDirectorySession.RetryCount;
                                }
                                stopwatch2.Stop();
                                num = (double)stopwatch2.ElapsedMilliseconds;
                                goto IL_19A;
                            }
                            goto IL_19A;
                        }
                    }
                    if ((CacheMode.Read & cacheModeForCurrentProcess) == CacheMode.Disabled || this.CacheSessionForDeletingOnly)
                    {
                        adcacheResultState = ADCacheResultState.CacheModeIsNotRead;
                    }
                    else
                    {
                        adcacheResultState = ADCacheResultState.SoftDeletedObject;
                    }
IL_19A:
                    if (tresult != null && tresult.Id != null)
                    {
                        TSession session5 = this.GetSession();
                        if (ADSession.ShouldFilterCNFObject(session5.SessionSettings, tresult.Id))
                        {
                            tresult            = default(TResult);
                            adcacheResultState = ADCacheResultState.CNFedObject;
                        }
                        else
                        {
                            TSession session6 = this.GetSession();
                            if (ADSession.ShouldFilterSoftDeleteObject(session6.SessionSettings, tresult.Id))
                            {
                                tresult            = default(TResult);
                                adcacheResultState = ADCacheResultState.SoftDeletedObject;
                            }
                            else
                            {
                                if (tresult.Id != null && tresult.Id.DomainId != null)
                                {
                                    TSession session7 = this.GetSession();
                                    if (!session7.SessionSettings.PartitionId.Equals(tresult.Id.GetPartitionId()))
                                    {
                                        if (ExEnvironment.IsTest)
                                        {
                                            TSession session8 = this.GetSession();
                                            if (session8.SessionSettings.PartitionId.ForestFQDN.EndsWith(tresult.Id.GetPartitionId().ForestFQDN, StringComparison.OrdinalIgnoreCase))
                                            {
                                                goto IL_341;
                                            }
                                        }
                                        ExEventLog.EventTuple tuple_WrongObjectReturned = DirectoryEventLogConstants.Tuple_WrongObjectReturned;
                                        string   name     = typeof(TResult).Name;
                                        object[] array    = new object[2];
                                        object[] array2   = array;
                                        int      num6     = 0;
                                        TSession session9 = this.GetSession();
                                        array2[num6] = session9.SessionSettings.PartitionId.ForestFQDN;
                                        array[1]     = tresult.Id.GetPartitionId().ForestFQDN;
                                        Globals.LogEvent(tuple_WrongObjectReturned, name, array);
                                        tresult            = default(TResult);
                                        adcacheResultState = ADCacheResultState.WrongForest;
                                        goto IL_3E1;
                                    }
                                }
IL_341:
                                TSession session10 = this.GetSession();
                                if (session10.SessionSettings.CurrentOrganizationId != OrganizationId.ForestWideOrgId)
                                {
                                    TSession       session11             = this.GetSession();
                                    OrganizationId currentOrganizationId = session11.SessionSettings.CurrentOrganizationId;
                                    if (!tresult.Id.IsDescendantOf(currentOrganizationId.OrganizationalUnit) && !tresult.Id.IsDescendantOf(currentOrganizationId.ConfigurationUnit.Parent))
                                    {
                                        tresult            = default(TResult);
                                        adcacheResultState = ADCacheResultState.OranizationIdMismatch;
                                    }
                                }
                            }
                        }
                    }
                    else if (tresult != null)
                    {
                        tresult = default(TResult);
                    }
                    else
                    {
                        adcacheResultState = ADCacheResultState.NotFound;
                    }
IL_3E1:
                    adobject = (tresult as ADObject);
                }
                catch (Exception ex)
                {
                    tresult            = default(TResult);
                    adcacheResultState = ADCacheResultState.ExceptionHappened;
                    Globals.LogEvent(DirectoryEventLogConstants.Tuple_CallADCacheServiceFailed, typeof(TResult).Name, new object[]
                    {
                        ex.ToString()
                    });
                    text = ex.ToString();
                }
                if (tresult == null)
                {
                    traceState |= CompositeDirectorySession <TSession> .TraceState.ADRead;
                    stopwatch2  = Stopwatch.StartNew();
                    tresult     = query(this.GetSession());
                    adobject    = (tresult as ADObject);
                    stopwatch2.Stop();
                    num4 = (double)stopwatch2.ElapsedMilliseconds;
                    stopwatch2.Restart();
                    bool flag2 = true;
                    if (adobject != null)
                    {
                        TSession session12 = this.GetSession();
                        if (!session12.ReadOnly && CompositeDirectorySession <TSession> .ExchangeConfigUnitCUType.Equals(adobject.GetType()) && OrganizationId.ForestWideOrgId.Equals(adobject.OrganizationId))
                        {
                            ExTraceGlobals.SessionTracer.TraceWarning <string>((long)this.GetHashCode(), "Newly created ExchangeCU with organizationId equals to RootOrgId, ignored till is fully populated. DN {0}", tresult.GetDistinguishedNameOrName());
                            flag2 = false;
                        }
                    }
                    if (tresult != null && CacheUtils.GetObjectTypeFor(tresult.GetType(), false) == ObjectType.Unknown)
                    {
                        flag2 = false;
                    }
                    if (tresult != null && ((CacheMode.SyncWrite | CacheMode.AsyncWrite) & cacheModeForCurrentProcess) != CacheMode.Disabled && tresult.Id != null && !tresult.Id.IsDeleted && flag2)
                    {
                        traceState |= CompositeDirectorySession <TSession> .TraceState.CacheInsert;
                        if ((CacheMode.SyncWrite & cacheModeForCurrentProcess) != CacheMode.Disabled)
                        {
                            try
                            {
                                this.CacheInsert <TResult>(tresult, getAdditionalKeys, properties);
                                goto IL_5C8;
                            }
                            catch (Exception ex2)
                            {
                                Globals.LogEvent(DirectoryEventLogConstants.Tuple_CallADCacheServiceFailed, "CacheInsert", new object[]
                                {
                                    ex2.ToString()
                                });
                                text += ex2.Message;
                                goto IL_5C8;
                            }
                        }
                        TSession session13 = this.GetSession();
                        if (session13.ReadOnly)
                        {
                            this.AsyncCacheInsert <TResult>(tresult, getAdditionalKeys, properties);
                        }
                        else
                        {
                            adcacheResultState |= ADCacheResultState.WritableSession;
                        }
                    }
IL_5C8:
                    stopwatch2.Stop();
                    num3 = (double)stopwatch2.ElapsedMilliseconds;
                }
                if (adobject != null)
                {
                    adobject.m_Session = this;
                }
            }
            finally
            {
                stopwatch.Stop();
                string   text2                   = CachePerformanceTracker.StopLogging();
                string   operation               = "Read";
                string   dn                      = (tresult != null) ? tresult.GetDistinguishedNameOrName() : "<NULL>";
                DateTime whenReadUTC             = (tresult != null) ? ((tresult.WhenReadUTC != null) ? tresult.WhenReadUTC.Value : DateTime.MinValue) : DateTime.MinValue;
                long     elapsedMilliseconds     = stopwatch.ElapsedMilliseconds;
                long     wcfGetProcessingTime    = (long)num;
                long     wcfRemoveProcessingTime = (long)num2;
                long     wcfPutProcessingTime    = (long)num3;
                long     adProcessingTime        = (long)num4;
                bool     isNewProxyObject        = flag;
                int      retryCount              = num5;
                string   objectType              = (tresult != null) ? tresult.GetType().Name : typeof(TResult).Name;
                string   cachePerformanceTracker = text2;
                Guid     activityId              = guid;
                TSession session14               = this.GetSession();
                CacheProtocolLog.BeginAppend(operation, dn, whenReadUTC, elapsedMilliseconds, wcfGetProcessingTime, wcfRemoveProcessingTime, wcfPutProcessingTime, adProcessingTime, isNewProxyObject, retryCount, objectType, cachePerformanceTracker, activityId, session14.CallerInfo, string.Format("ResultState:{0};{1}", (int)adcacheResultState, text));
                ExTraceGlobals.SessionTracer.TraceDebug((long)this.GetHashCode(), "ExecuteSingleObjectQueryWithFallback. Cache Mode {0}. TraceState {1}. DN {2}. WhenRead {3}. IsCached {4}.", new object[]
                {
                    cacheModeForCurrentProcess,
                    traceState,
                    (tresult != null) ? tresult.GetDistinguishedNameOrName() : "<NULL>",
                    (tresult != null) ? ((tresult.WhenReadUTC != null) ? tresult.WhenReadUTC.Value.ToString() : "<NULL>") : "<NULL>",
                    tresult != null && tresult.IsCached
                });
                ExTraceGlobals.SessionTracer.TracePerformance((long)this.GetHashCode(), "ExecuteSingleObjectQueryWithFallback.  Cache Mode {0}. TraceState {1}. DN {2}. TotalTime {3}. GetCacheTime {4}. RemoveCacheTime {5}. PutCacheTime {6}. ADTime {7}. WCFDetails [{8}]", new object[]
                {
                    cacheModeForCurrentProcess,
                    traceState,
                    (tresult != null) ? tresult.GetDistinguishedNameOrName() : "<NULL>",
                    stopwatch.ElapsedMilliseconds,
                    num,
                    num2,
                    num3,
                    num4,
                    text2
                });
                if (tresult != null)
                {
                    ADProviderPerf.UpdateADDriverCacheHitRate(tresult.IsCached);
                }
            }
            return(tresult);
        }