在 Simple Injector 中通过名称获取已知注册

Getting known registration by name in Simple Injector

我正在尝试获取中介请求的实例,我认为使用 IoC 是可行的。

鉴于以下注册:

container.Register(typeof(IRequest<>), assemblies);
container.Register(typeof(IRequestHandler<,>), assemblies);

以及以下class

public class SubtractRequest: IRequest<int>
{
    public int Left { get; set; }
    public int Right{ get; set; }

    public SubtractRequest() { }

    internal class Handler : IRequestHandler<SubtractRequest, int>
    {
        public Handler() {}

        public string Handle(SubtractRequest request)
        {
            return request.Left - request.Right;
        }
    }
}

按名称解析实例的最佳方法是什么 "SubtractRequest"

我的意图是获取一个 JSON-RPC 对象,如下所示:{"jsonrpc": "2.0", "method": "subtract", "params": [42, 23], "id": 1},提取方法,然后通过该方法名称获取该中介请求的实例。

var request = JsonConvert.DeserializeObject<JsonRpcRequest>(jsonRpcRequest);
var mediatorRequest = GetRequestByName($"{request.Method}Request"); //Via IoC?
//SetParams(mediatorRequest) [todo]
var result = mediator.Send(mediatorRequest).Result;

基本上我正在尝试找出如何最好地实现我的 GetRequestByName() 方法以获得正确的调解器请求。

这是一个非常宽泛的问题,答案取决于您使用的框架以及这些数据的输入方式,但总的来说,您必须:

  • 将传入请求与特定 IRequest<TResponse> 消息相关联。
  • 从该请求消息类型中提取 TResponse 类型。
  • 将传入请求反序列化为请求类型。
  • 根据请求类型和 TResponse 类型创建一个封闭的通用 IRequestHandler<TRequest, TResponse> 版本。
  • 解决从 Container.
  • 关闭 IRequestHandler<TRequest, TResponse>
  • 调用处理程序的 Handle 方法。

Github 上有一个参考架构应用程序,在 Web API 项目中称为 SOLID Services that contains examples on how to do this. Especially take a look at the QueryDelegatingHandler 实现,因为它基本上可以满足您的需要。您可能想下载完整的项目并试用它,但请注意接口的名称略有不同。在您调用 IRequest<TResponse>IRequestHandler<TRequest, TResponse> 的地方,示例项目调用此 IQuery<TResult>IQueryHandler<TQuery, TResult>。不过思路是一样的。

最后提醒一下,请删除以下注册:

container.Register(typeof(IRequest<>), assemblies);

IRequest<TResponse> 是消息的定义。一条消息是一个 DTO,创建它们与您的 DI 容器无关。将它们注册到您的容器中可能会阻止您成功验证容器的配置。您唯一应该注册的是 IRequestHandler<,>.

更新:

您的代码基本上应该是这样的:

Type requestType = GetRequestTypeByName($"{request.Method}Request");

dynamic request = JsonConvert.DeserializeObject(requestType, jsonRpcRequest);

object result = ((dynamic)mediator).Send(request).Result;

您将必须实施 GetRequestTypeByName。这是 而不是 DI 容器可以帮助您的东西。只需使用反射检查程序集中的类型并找到名为 {request.Method}Request.

的类型