<commit_before>﻿using System;
using System.Threading.Tasks;
using AspectCore.Lite.Abstractions;
using System.Reflection;
using AspectCore.Lite.Extensions;
using Nito.AsyncEx;
using AspectCore.Lite.Internal.Generators;

namespace AspectCore.Lite.Internal
{
    internal sealed class AspectExecutor : IAspectExecutor
    {
        private readonly IJoinPoint joinPoint;
        private readonly IAspectContextFactory aspectContextFactory;
        private readonly IServiceProvider serviceProvider;
        private readonly IInterceptorMatcher interceptorMatcher;
        private readonly INamedMethodMatcher namedMethodMatcher;
        private readonly IPropertyInjector propertyInjector;
        public AspectExecutor(
            IServiceProvider serviceProvider ,
            IJoinPoint joinPoint ,
            IAspectContextFactory aspectContextFactory ,
            IInterceptorMatcher interceptorMatcher ,
            INamedMethodMatcher namedMethodMatcher,
            IPropertyInjector propertyInjector)
        {
            this.serviceProvider = serviceProvider;
            this.joinPoint = joinPoint;
            this.aspectContextFactory = aspectContextFactory;
            this.interceptorMatcher = interceptorMatcher;
            this.namedMethodMatcher = namedMethodMatcher;
            this.propertyInjector = propertyInjector;
        }

        public TResult Execute<TResult>(object targetInstance , object proxyInstance , Type serviceType , string method , params object[] args)
        {
            return AsyncContext.Run(() => ExecuteAsync<TResult>(targetInstance , proxyInstance , serviceType , method , args));
        }

        public async Task<TResult> ExecuteAsync<TResult>(object targetInstance , object proxyInstance , Type serviceType , string method , params object[] args)
        {
            var serviceMethod = namedMethodMatcher.Match(serviceType , method , args);
            var parameters = new ParameterCollection(args , serviceMethod.GetParameters());
            var returnParameter = new ReturnParameterDescriptor(default(object) , serviceMethod.ReturnParameter);
            var targetMethod = namedMethodMatcher.Match(targetInstance.GetType() , method , args);
            var target = new Target(targetMethod , serviceType , targetInstance.GetType() , targetInstance) { ParameterCollection = parameters };
            var proxyMethod = namedMethodMatcher.Match(proxyInstance.GetType() , GeneratorHelper.GetMethodName(serviceType , method) , args);
            var proxy = new Proxy(proxyInstance , proxyMethod , proxyInstance.GetType());
            var interceptors = interceptorMatcher.Match(serviceMethod , serviceType.GetTypeInfo());
            joinPoint.MethodInvoker = target;
            interceptors.ForEach(interceptor =>
            {
                propertyInjector.Injection(interceptor);
                joinPoint.AddInterceptor(next => ctx => interceptor.ExecuteAsync(ctx, next));
            });

            using (var context = aspectContextFactory.Create())
            {
                var internalContext = context as AspectContext;
                if (internalContext != null)
                {
                    internalContext.Parameters = parameters;
                    internalContext.ReturnParameter = returnParameter;
                    internalContext.Target = target;
                    internalContext.Proxy = proxy;
                }
                try
                {
                    await joinPoint.Build()(context);
                    return await CastAsyncResult<TResult>(context.ReturnParameter.Value);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

        private static async Task<TResult> CastAsyncResult<TResult>(object value)
        {
            var taskResult = value as Task<TResult>;

            if (taskResult != null)
            {
                return await taskResult;
            }

            var task = value as Task;

            if (task != null)
            {
                await task;
                return default(TResult);
            }

            return (TResult)value;
        }
    }
}<commit_msg>Add Interceptor resource release<commit_after>﻿using System;
using System.Threading.Tasks;
using AspectCore.Lite.Abstractions;
using System.Reflection;
using AspectCore.Lite.Extensions;
using Nito.AsyncEx;
using AspectCore.Lite.Internal.Generators;

namespace AspectCore.Lite.Internal
{
    internal sealed class AspectExecutor : IAspectExecutor
    {
        private readonly IJoinPoint joinPoint;
        private readonly IAspectContextFactory aspectContextFactory;
        private readonly IServiceProvider serviceProvider;
        private readonly IInterceptorMatcher interceptorMatcher;
        private readonly INamedMethodMatcher namedMethodMatcher;
        private readonly IPropertyInjector propertyInjector;
        public AspectExecutor(
            IServiceProvider serviceProvider ,
            IJoinPoint joinPoint ,
            IAspectContextFactory aspectContextFactory ,
            IInterceptorMatcher interceptorMatcher ,
            INamedMethodMatcher namedMethodMatcher,
            IPropertyInjector propertyInjector)
        {
            this.serviceProvider = serviceProvider;
            this.joinPoint = joinPoint;
            this.aspectContextFactory = aspectContextFactory;
            this.interceptorMatcher = interceptorMatcher;
            this.namedMethodMatcher = namedMethodMatcher;
            this.propertyInjector = propertyInjector;
        }

        public TResult Execute<TResult>(object targetInstance , object proxyInstance , Type serviceType , string method , params object[] args)
        {
            return AsyncContext.Run(() => ExecuteAsync<TResult>(targetInstance , proxyInstance , serviceType , method , args));
        }

        public async Task<TResult> ExecuteAsync<TResult>(object targetInstance , object proxyInstance , Type serviceType , string method , params object[] args)
        {
            var serviceMethod = namedMethodMatcher.Match(serviceType , method , args);
            var parameters = new ParameterCollection(args , serviceMethod.GetParameters());
            var returnParameter = new ReturnParameterDescriptor(default(object) , serviceMethod.ReturnParameter);
            var targetMethod = namedMethodMatcher.Match(targetInstance.GetType() , method , args);
            var target = new Target(targetMethod , serviceType , targetInstance.GetType() , targetInstance) { ParameterCollection = parameters };
            var proxyMethod = namedMethodMatcher.Match(proxyInstance.GetType() , GeneratorHelper.GetMethodName(serviceType , method) , args);
            var proxy = new Proxy(proxyInstance , proxyMethod , proxyInstance.GetType());
            var interceptors = interceptorMatcher.Match(serviceMethod , serviceType.GetTypeInfo());

            joinPoint.MethodInvoker = target;

            interceptors.ForEach(interceptor =>
            {
                propertyInjector.Injection(interceptor);
                joinPoint.AddInterceptor(next => ctx => interceptor.ExecuteAsync(ctx, next));
            });

            using (var context = aspectContextFactory.Create())
            {
                var internalContext = context as AspectContext;
                if (internalContext != null)
                {
                    internalContext.Parameters = parameters;
                    internalContext.ReturnParameter = returnParameter;
                    internalContext.Target = target;
                    internalContext.Proxy = proxy;
                }
                try
                {
                    await joinPoint.Build()(context);
                    return await CastAsyncResult<TResult>(context.ReturnParameter.Value);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    interceptors.ForEach(interceptor => (interceptor as IDisposable)?.Dispose());
                }
            }
        }

        private static async Task<TResult> CastAsyncResult<TResult>(object value)
        {
            var taskResult = value as Task<TResult>;

            if (taskResult != null)
            {
                return await taskResult;
            }

            var task = value as Task;

            if (task != null)
            {
                await task;
                return default(TResult);
            }

            return (TResult)value;
        }
    }
}
{'fraction_non_alphanumeric': 0.06890970054341543, 'fraction_numerical': 0.0, 'mean_word_length': 2.1204906204906204, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5099269', 'n_tokens_mistral': 1939, 'n_tokens_neox': 1896, 'n_words': 448}