def add_resource(self, value, name: str = 'default', context_attr: str = None,
                     types: Union[type, Sequence[type]] = ()) -> None:
        """
        Add a resource to this context.

        This will cause a ``resource_added`` event to be dispatched.

        :param value: the actual resource value
        :param name: name of this resource (unique among all its registered types within a single
            context)
        :param context_attr: name of the context attribute this resource will be accessible as
        :param types: type(s) to register the resource as (omit to use the type of ``value``)
        :raises asphalt.core.context.ResourceConflict: if the resource conflicts with an existing
            one in any way

        """
        assert check_argument_types()
        self._check_closed()
        if isinstance(types, type):
            types = (types,)
        elif not types:
            types = (type(value),)

        if value is None:
            raise ValueError('"value" must not be None')
        if not resource_name_re.fullmatch(name):
            raise ValueError('"name" must be a nonempty string consisting only of alphanumeric '
                             'characters and underscores')
        if context_attr and getattr_static(self, context_attr, None) is not None:
            raise ResourceConflict('this context already has an attribute {!r}'.format(
                context_attr))
        for resource_type in types:
            if (resource_type, name) in self._resources:
                raise ResourceConflict(
                    'this context already contains a resource of type {} using the name {!r}'.
                    format(qualified_name(resource_type), name))

        resource = ResourceContainer(value, tuple(types), name, context_attr, False)
        for type_ in resource.types:
            self._resources[(type_, name)] = resource

        if context_attr:
            setattr(self, context_attr, value)

        # Notify listeners that a new resource has been made available
        self.resource_added.dispatch(types, name, False)
Add a resource to this context.

        This will cause a ``resource_added`` event to be dispatched.

        :param value: the actual resource value
        :param name: name of this resource (unique among all its registered types within a single
            context)
        :param context_attr: name of the context attribute this resource will be accessible as
        :param types: type(s) to register the resource as (omit to use the type of ``value``)
        :raises asphalt.core.context.ResourceConflict: if the resource conflicts with an existing
            one in any way