final protected function addRole(object $data, AbstractRole $role): BoundedRoleInterface
    {
        return new class ($role, $data) implements BoundedRoleInterface
        {
            use DelegatorTrait;

            public function __construct(AbstractRole $role, object $data)
            {
                if (false === $role->supports($data)) {
                    throw new InvalidArgumentException(
                        sprintf(
                            'Role "%s" does not support for current data',
                            get_class($role)
                        )
                    );
                }

                $this->attach($this->invoke($role, 'attach', $data));
            }

            /**
             * Extract data from bounded roles.
             *
             * @return object
             */
            public function extract(): object
            {
                return $this->invoke($this->getInstance(), 'extract');
            }

            /**
             * Invoke closure method from role.
             *
             * @param AbstractRole $role
             * @param string       $method
             * @param array        ...$args
             *
             * @return mixed
             */
            private function invoke(AbstractRole $role, string $method, ...$args)
            {
                $method = new ReflectionMethod(get_class($role), $method);
                $method->setAccessible(true);

                return $method->invoke($role, ...$args);
            }
        };
    }