Example #1
0
        public override void Intercept(IInvocation invocation)
        {
            if (invocation.IsAction())
            {
                invocation.Proceed();
                return;
            }

            var(expectation, addOrUpdateCache, getFromCache) = Expectations.FirstOrDefault(x => x.expectation.IsHit(invocation));
            var cacheKey = JsonConvert.SerializeObject(invocation.Arguments);

            if (expectation != null)
            {
                if (CachedInvocations.TryGetValue(expectation.Identifier, out var cachedInvocation))
                {
                    if (cachedInvocation.TryGetValue(cacheKey, out var cachedValue))
                    {
                        if (expectation.IsExpired(cachedValue.invocationResult, cachedValue.invocationDateTime))
                        {
                            invocation.Proceed();

                            addOrUpdateCache
                            .Invoke
                            (
                                invocation.ReturnValue,
                                cachedInvocation,
                                cacheKey
                            );
                        }
                        else
                        {
                            invocation.ReturnValue = getFromCache.Invoke(cachedValue.invocationResult);
                        }
                    }
                    else
                    {
                        invocation.Proceed();

                        addOrUpdateCache
                        .Invoke
                        (
                            invocation.ReturnValue,
                            cachedInvocation,
                            cacheKey
                        );
                    }
                }
                else
                {
                    invocation.Proceed();

                    var cache = new ConcurrentDictionary <string, (object invocationResult, DateTime invocationDateTime)>();

                    addOrUpdateCache
                    .Invoke
                    (
                        invocation.ReturnValue,
                        cache,
                        cacheKey
                    );

                    CachedInvocations
                    .TryAdd
                    (
                        expectation.Identifier,
                        cache
                    );
                }
            }
            else
            {
                var returnType = invocation.Method.ReturnType;

                expectation      = Expectation.FromInvocation(invocation, _expirationDelegate);
                addOrUpdateCache = BuildAddOrUpdateDelegateForType(returnType);
                getFromCache     = BuildGetFromCacheDelegateForType(returnType);

                Expectations
                .Add
                (
                    (
                        expectation,
                        addOrUpdateCache,
                        getFromCache
                    )
                );

                var cache = new ConcurrentDictionary <string, (object invocationResult, DateTime invocationDateTime)>();
                CachedInvocations.TryAdd(expectation.Identifier, cache);

                invocation.Proceed();

                addOrUpdateCache
                .Invoke
                (
                    invocation.ReturnValue,
                    cache,
                    cacheKey
                );
            }
        }