// ***********************************************************************
// Assembly         : XYY.Core
// Author           : 陈汉林
// Created          : 08-24-2016
//
// Last Modified By : 陈汉林
// Last Modified On : 08-24-2016
// ***********************************************************************
// <copyright file="ConnectionInterceptor.cs" company="澳鹏">
//     Copyright (c) 澳鹏. All rights reserved.
// </copyright>
// <summary></summary>
// *********************************************************************** 
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using AspectCore.DynamicProxy;
using System.Collections.Concurrent;

/// <summary>
/// The Infrastructure namespace.
/// </summary>
namespace XYY.Core.Standard.Data.Infrastructure
{

    public static class InterceptorAttribut
    {
        private static readonly ConcurrentDictionary<MethodInfo, object[]>
                       MethodAttributes = new ConcurrentDictionary<MethodInfo, object[]>();
        public static T GetAttribute<T>(this AspectContext context) where T : Attribute
        {
            MethodInfo method = context.ServiceMethod;

            var attributes = MethodAttributes.GetOrAdd(method, method.GetCustomAttributes(true));
            var attribute = attributes.FirstOrDefault(x => typeof(T).IsAssignableFrom(x.GetType()));
            if (attribute is T)
            {
                return (T)attribute;
            }
            return null;
        }
    }

    /// <summary>
    /// 拦截器.
    /// </summary>
    public class ConnectionInterceptorAttribute : AbstractInterceptorAttribute
    {
        /// <summary>
        /// The _unit of work
        /// </summary>
        /// [FromContainer]
        IUnitOfWork _unitOfWork;
        /// <summary>
        /// The _connection
        /// </summary>
        IDbConnection _connection;
        /// <summary>
        /// Initializes a new instance of the <see cref="ConnectionInterceptor"/> class.
        /// </summary>
        /// <param name="connection">The connection.</param>
        /// <param name="unitOfWork">The unit of work.</param>
        public ConnectionInterceptorAttribute()
        {
            //_unitOfWork = unitOfWork;
            //_connection = connection;
        }

        public override Task Invoke(AspectContext context, AspectDelegate next)
        {
            _unitOfWork = context.ServiceProvider.GetService(typeof(IUnitOfWork)) as IUnitOfWork;
            _connection = context.ServiceProvider.GetService(typeof(IDbConnection)) as IDbConnection;
            MethodInfo method = context.ServiceMethod;
            var nonTrans = context.GetAttribute<NonTransAttribute>();
            var isStartWithGet = method.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase);
            if (nonTrans == null && !isStartWithGet)
            {
                _unitOfWork.Connection = _unitOfWork.Connection ?? _connection;
                if (_unitOfWork.Connection.State != ConnectionState.Open && _unitOfWork.Connection.State != ConnectionState.Connecting)
                {//初始化连接
                    _unitOfWork.Connection.Open();
                }

                //方法不含NonTrans特性，或者方法不是Get开头的，则需要开启事务
                try
                {
                    _unitOfWork.Transaction = _unitOfWork.Transaction ?? _unitOfWork.Connection.BeginTransaction();
                }
                catch
                {
                    //尝试重新开启事务
                    _unitOfWork.Transaction = _unitOfWork.Transaction ?? _unitOfWork.Connection.BeginTransaction();
                }
            }
            return context.Invoke(next);

        }

    }
}
