基于@Greg 的回答,我在init方法中添加了一个初始化检查:
为 flask-restful api 创建和调用 Todo 资源类:
todo = Todo.create(InMemoryTodoRepository())
api.add_resource(todo, '/api/todos/<todo_id>')
Todo 资源类:
from flask_restful import reqparse, abort, Resource
from server.ApiResources.DTOs.TodoDTO import TodoDTO
from server.Repositories.ITodoRepository import ITodoRepository
from server.Utils.Exceptions import InvalidInstantiationError
from server.Utils.GeneralUtils import member_exists
class Todo(Resource):
"""shows a single todo item and lets you delete a todo item
use the 'create' class method to instantiate the class
"""
def __init__(self):
if not member_exists(self, "todo_repository", of_type=ITodoRepository):
raise InvalidInstantiationError("Todo", "todo_repository", "ITodoRepository", "create")
self._parser = reqparse.RequestParser()
self._parser.add_argument('task', type=str)
@classmethod
def create(cls, todo_repository):
"""
:param todo_repository: an instance of ITodoRepository
:return: class object of Todo Resource
"""
cls.todo_repository = todo_repository
return cls
member_exists 辅助方法:
def member_exists(obj, member, of_type):
member_value = getattr(obj, member, None)
if member_value is None:
return False
if not isinstance(member_value, of_type):
return False
return True
和自定义异常类:
class InvalidInstantiationError(Exception):
def __init__(self, origin_class_name, missing_argument_name, missing_argument_type, instantiation_method_to_use):
message = """Invalid instantiation for class '{class_name}':
missing instantiation argument '{arg}' of type '{arg_type}'.
Please use the '{method_name}' factory class method""" \
.format(class_name=origin_class_name,
arg=missing_argument_name,
arg_type=missing_argument_type,
method_name=instantiation_method_to_use)
# Call the base class constructor with the parameters it needs
super(InvalidInstantiationError, self).__init__(message)
因此,尝试使用默认构造函数最终会得到这个异常:
server.Utils.Exceptions.InvalidInstantiationError:类“Todo”的无效实例化:缺少“ITodoRepository”类型的实例化参数“todo_repository”。请使用“创建”工厂类方法
编辑:这对于将依赖注入与flask-restful api资源类(有或没有IoC)一起使用很有用
编辑2:
我们甚至可以更简洁并添加另一个帮助功能(准备导入):
def must_have(obj, member, of_type, use_method):
if not member_exists(obj, member, of_type=of_type):
raise InvalidInstantiationError(obj.__class__.__name__,
member,
of_type.__name__,
use_method)
然后像这样在构造函数中使用它:
from server.Utils.GeneralUtils import must_have
class Todo(Resource):
def __init__(self):
must_have(self,
member="todo_repository",
of_type=ITodoRepository,
use_method=Todo.create.__name__)