【发布时间】:2023-03-28 12:25:01
【问题描述】:
我正在尝试用装饰器包装 Web API 控制器(IHttpController 实现),但是当我这样做时,Web API 会引发异常,因为它以某种方式期待实际的实现。
将装饰器应用于控制器是我成功应用于 MVC 控制器的一个技巧,我显然喜欢在 Web API 中做同样的事情。
我创建了一个自定义的IHttpControllerActivator,它允许解析修饰的IHttpController 实现。这是一个剥离的实现:
public class CrossCuttingConcernHttpControllerActivator : IHttpControllerActivator {
private readonly Container container;
public CrossCuttingConcernHttpControllerActivator(Container container) {
this.container = container;
}
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = (IHttpController)this.container.GetInstance(controllerType);
// Wrap the instance in one or multiple decorators. Note that in reality, the
// decorator is applied by the container, but that doesn't really matter here.
return new MyHttpControllerDecorator(controller);
}
}
我的装饰器看起来像这样:
public class MyHttpControllerDecorator : IHttpController {
private readonly IHttpController decoratee;
public MyHttpControllerDecorator(IHttpController decoratee) {
this.decoratee = decoratee;
}
public Task<HttpResponseMessage> ExecuteAsync(
HttpControllerContext controllerContext,
CancellationToken cancellationToken)
{
// this decorator does not add any logic. Just the minimal amount of code to
// reproduce the issue.
return this.decoratee.ExecuteAsync(controllerContext, cancellationToken);
}
}
但是,当我运行我的应用程序并请求 ValuesController 时,Web API 会向我抛出以下 InvalidCastException:
无法转换类型为“WebApiTest.MyHttpControllerDecorator”的对象 输入“WebApiTest.Controllers.ValuesController”。
堆栈跟踪:
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)
就好像 Web API 为我们提供了 IHttpController 抽象但跳过它并仍然依赖于实现本身。这当然会严重违反依赖倒置原则,并使抽象完全无用。所以我可能做错了什么。
我做错了什么?如何愉快地装饰我的 API 控制器?
【问题讨论】:
标签: c# dependency-injection asp.net-web-api decorator