//public static TInterface CreateHandler<TInterface, THandler>(this IResolver resolver) where TInterface : class where THandler : IInterfaceHandler
        //{
        //    var typeInfo = CreateTypeInfo(typeof(TInterface), typeof(THandler));
        //    var obj = (TInterface)Resolver.CreateInstance(resolver, typeInfo);
        //    return obj;
        //}

        public static TInterface CreateHandler <TInterface, THandler>(this IResolverSession session) where TInterface : class where THandler : IInterfaceHandler
        {
            var typeInfo = CreateTypeInfo(typeof(TInterface), typeof(THandler), session.Resolve <IMethodContextInfoProvider>());
            var obj      = (TInterface)session.CreateInstance(typeInfo);

            return(obj);
        }
        public static object CreateInstance(this IResolverSession session, ConstructorInfo constructorInfo)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (constructorInfo == null)
            {
                throw new ArgumentNullException(nameof(constructorInfo));
            }

            var parameters = constructorInfo.GetParameters();
            var arguments  = parameters.Select(p => session.Resolve(p.ParameterType)).ToArray();

            return(constructorInfo.Invoke(arguments));
        }
        //public virtual async Task<object> HandleAsync(object[] requests, CancellationToken cancellationToken)
        //{
        //    return await HandleAsync(new Resolver(), requests, cancellationToken);
        //}

        public virtual async Task <object> HandleAsync(IResolverSession session, object[] requests, CancellationToken cancellationToken)
        {
            if (requests == null)
            {
                throw new ArgumentNullException(nameof(requests));
            }

            if (classRoles.Length > 0 || methodRoles.Length > 0)
            {
                if (!session.TryResolve <IRole>(out var role))
                {
                    throw new UnauthorizedException(UnauthorizedReason.NoRoleProvider);
                }

                if (classRoles.Length > 0 && !classRoles.All(ar => ar.AnyOfRoles.Any(r => role.Contains(r))))
                {
                    throw new UnauthorizedException(UnauthorizedReason.ClassAccess);
                }

                if (methodRoles.Length > 0 && !methodRoles.All(ar => ar.AnyOfRoles.Any(r => role.Contains(r))))
                {
                    throw new UnauthorizedException(UnauthorizedReason.MethodAccess);
                }
            }

            var instance = session.Resolve(handlerType);

            var parameters    = method.GetParameters();
            var arguments     = new object[parameters.Length];
            var argumentIndex = 0;

            for (int i = 0; i < arguments.Length; i++)
            {
                if (session.TryResolve(parameters[i].ParameterType, out var arg))
                {
                    arguments[i] = arg;
                }
                else
                {
                    if (parameters[i].ParameterType.GetTypeInfo().IsAssignableFrom(typeof(CancellationToken)))
                    {
                        arguments[i] = cancellationToken;
                    }
                    else if (parameters[i].ParameterType.GetTypeInfo().IsAssignableFrom(typeof(IResolverSession)))
                    {
                        arguments[i] = session;
                    }
                    else
                    {
                        if (requests.Length > argumentIndex)
                        {
                            var req      = requests[argumentIndex];
                            var typeInfo = parameters[i].ParameterType.GetTypeInfo();
                            if (!typeInfo.IsClass || typeInfo.IsAssignableFrom(req.GetType()))
                            {
                                arguments[i] = req;
                                argumentIndex++;
                                continue;
                            }
                        }
                        arguments[i] = null;
                    }
                }
            }

            var result = method.Invoke(instance, arguments);

            if (result == null)
            {
                return(null);
            }

            if (result is Task)
            {
                var   task = (Task)result;
                await task;

                if (resultProperty != null)
                {
                    return(resultProperty.GetValue(result));
                }

                return(null);
            }

            return(result);
        }