选择有条件的注入实例
Selecting Injected Instance with Conditional
我有几个 类 从一个接口继承而来。我希望根据条件在控制器中加载和使用所需的服务。
控制器
public class GatewayController
{
private readonly IAction action;
public GatewayController(IAction action)
{
this.action = action;
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
try
{
var comId = gatewayRequest.CommandId;
switch (comId)
{
case (int) GuaranteeItemStatus.End:
return await action.Perform(gatewayRequest, cancellationToken); //must be use EndActionService
case (int) GuaranteeItemStatus.SendProduct:
return await action.Perform(gatewayRequest, cancellationToken); //must be use SendProductActionService
default:
return null;
}
}
catch (Exception ex)
{
return ApiResult.ToErrorModel("error");
}
}
}
父接口:
public interface IAction
{
Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken);
}
服务:
1-SendProductActionService:
public class SendProductActionService:IAction
{
public async Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
return ApiResult.ToSuccessModel("SendProduct");
}
}
2-EndActionService:
public class EndActionService:IAction
{
public async Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
return ApiResult.ToSuccessModel("EndAction");
}
}
可以注册并注入包含您所有 IAction
的 IEnumerable
。
首先,要确定哪个 IAction
对哪个命令作出反应,您可以添加一个 CommandId
属性:
public interface IAction
{
int CommandId { get; }
}
public class SendProductActionService : IAction
{
public int CommandId => (int)GuaranteeItemStatus.SendProduct;
}
public class EndActionService : IAction
{
public int CommandId => (int)GuaranteeItemStatus.End;
}
在您的 Startup.cs
中,您注册了所有操作:
services.AddScoped<IAction, SendProductActionService>();
services.AddScoped<IAction, EndActionService>();
然后在您的控制器中,注入所有 IAction
,并在需要时 select 注入适当的:
public class GatewayController
{
// map the command ID to the proper IAction
private readonly Dictionary<int, IAction> actions;
// inject all the services registered that implement IAction
public GatewayController(IEnumerable<IAction> actions)
{
this.actions = actions.ToDictionary(_ => _.CommandId);
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
// find the appropriate IAction
if (!actions.TryGetValue((int)gatewayRequest.CommandId, out var action)
return BadRequest();
return await action.Perform(gatewayRequest, cancellationToken);
}
}
在你的startup.cs
中:
services.AddScoped<SendProductActionService>();
services.AddScoped<EndActionService>();
services.AddScoped<Func<GuaranteeItemStatus, IAction>>(serviceProvider => status =>
{
switch (status)
{
case GuaranteeItemStatus.SendProduct:
return serviceProvider.GetService<SendProductActionService>();
case GuaranteeItemStatus.End:
return serviceProvider.GetService<EndActionService>();
default:
throw new InvalidOperationException();
}
});
您的控制器应该与此类似:
public class GatewayController
{
private readonly Func<GuaranteeItemStatus, IAction> actionProvider;
public GatewayController(Func<GuaranteeItemStatus, IAction> actionProvider)
{
this.actionProvider = actionProvider;
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
try
{
return await actionProvider((GuaranteeItemStatus)gatewayRequest.CommandId)
.Perform(gatewayRequest, cancellationToken);
}
catch (Exception ex)
{
return ApiResult.ToErrorModel("error");
}
}
}
我有几个 类 从一个接口继承而来。我希望根据条件在控制器中加载和使用所需的服务。
控制器
public class GatewayController
{
private readonly IAction action;
public GatewayController(IAction action)
{
this.action = action;
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
try
{
var comId = gatewayRequest.CommandId;
switch (comId)
{
case (int) GuaranteeItemStatus.End:
return await action.Perform(gatewayRequest, cancellationToken); //must be use EndActionService
case (int) GuaranteeItemStatus.SendProduct:
return await action.Perform(gatewayRequest, cancellationToken); //must be use SendProductActionService
default:
return null;
}
}
catch (Exception ex)
{
return ApiResult.ToErrorModel("error");
}
}
}
父接口:
public interface IAction
{
Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken);
}
服务:
1-SendProductActionService:
public class SendProductActionService:IAction
{
public async Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
return ApiResult.ToSuccessModel("SendProduct");
}
}
2-EndActionService:
public class EndActionService:IAction
{
public async Task<ApiResult> Perform(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
return ApiResult.ToSuccessModel("EndAction");
}
}
可以注册并注入包含您所有 IAction
的 IEnumerable
。
首先,要确定哪个 IAction
对哪个命令作出反应,您可以添加一个 CommandId
属性:
public interface IAction
{
int CommandId { get; }
}
public class SendProductActionService : IAction
{
public int CommandId => (int)GuaranteeItemStatus.SendProduct;
}
public class EndActionService : IAction
{
public int CommandId => (int)GuaranteeItemStatus.End;
}
在您的 Startup.cs
中,您注册了所有操作:
services.AddScoped<IAction, SendProductActionService>();
services.AddScoped<IAction, EndActionService>();
然后在您的控制器中,注入所有 IAction
,并在需要时 select 注入适当的:
public class GatewayController
{
// map the command ID to the proper IAction
private readonly Dictionary<int, IAction> actions;
// inject all the services registered that implement IAction
public GatewayController(IEnumerable<IAction> actions)
{
this.actions = actions.ToDictionary(_ => _.CommandId);
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
// find the appropriate IAction
if (!actions.TryGetValue((int)gatewayRequest.CommandId, out var action)
return BadRequest();
return await action.Perform(gatewayRequest, cancellationToken);
}
}
在你的startup.cs
中:
services.AddScoped<SendProductActionService>();
services.AddScoped<EndActionService>();
services.AddScoped<Func<GuaranteeItemStatus, IAction>>(serviceProvider => status =>
{
switch (status)
{
case GuaranteeItemStatus.SendProduct:
return serviceProvider.GetService<SendProductActionService>();
case GuaranteeItemStatus.End:
return serviceProvider.GetService<EndActionService>();
default:
throw new InvalidOperationException();
}
});
您的控制器应该与此类似:
public class GatewayController
{
private readonly Func<GuaranteeItemStatus, IAction> actionProvider;
public GatewayController(Func<GuaranteeItemStatus, IAction> actionProvider)
{
this.actionProvider = actionProvider;
}
[HttpPost("gateway")]
public async Task<ApiResult> Gateway(GatewayRequest gatewayRequest, CancellationToken cancellationToken)
{
try
{
return await actionProvider((GuaranteeItemStatus)gatewayRequest.CommandId)
.Perform(gatewayRequest, cancellationToken);
}
catch (Exception ex)
{
return ApiResult.ToErrorModel("error");
}
}
}