public function set($property, $value = null, array $options = [])
    {
        if (is_string($property) && $property !== '') {
            $guard = false;
            $property = [$property => $value];
        } else {
            $guard = true;
            $options = (array)$value;
        }

        if (!is_array($property)) {
            throw new InvalidArgumentException('Cannot set an empty property');
        }
        $options += ['setter' => true, 'guard' => $guard];

        foreach ($property as $p => $value) {
            if ($options['guard'] === true && !$this->isAccessible($p)) {
                continue;
            }

            $this->setDirty($p, true);

            if (!array_key_exists($p, $this->_original) &&
                array_key_exists($p, $this->_properties) &&
                $this->_properties[$p] !== $value
            ) {
                $this->_original[$p] = $this->_properties[$p];
            }

            if (!$options['setter']) {
                $this->_properties[$p] = $value;
                continue;
            }

            $setter = static::_accessor($p, 'set');
            if ($setter) {
                $value = $this->{$setter}($value);
            }
            $this->_properties[$p] = $value;
        }

        return $this;
    }