Web API控制器构造函数中的具体类型
本文关键字:类型 API 控制器 构造函数 Web | 更新日期: 2023-09-27 18:02:33
我有一个Web API控制器FooController
看起来像
public class FooController : ApiController
{
private readonly IDictionary<string, string> messageDictionary;
private readonly TimeSpan timeout;
public FooController(IDictionary<string, string> messageDictionary, TimeSpan timeout)
{
// set fields
}
public async Task<IHttpActionResult> Post([FromBody] string message)
{
try
{
using (var tokenSource = new CancellationTokenSource(timeout))
{
CancellationToken token = tokenSource.Token;
// call some api
token.ThrowIfCancellationRequested();
// do some other stuff
token.ThrowIfCancellationRequested();
return Ok();
}
}
catch
{
// LogException
return InternalServerError();
}
}
}
当我尝试使用这个控制器时,我得到一个错误,指出没有默认构造函数,这很好,这是显而易见的。
我正在使用自定义配置部分从web.config
文件中读取messageDictionary
的值,Global.asax
文件
private IDictionary<string, string> messageDictionary;
private TimeSpan controllerTimeout;
// ...
void Application_Start(object sender, EventArgs e)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
messageDictionary = BuildMessageDictionaryFromConfig();
controllerTimeout = GetControllerTimeoutFromConfig();
}
我的目标是让控制器不必担心从配置中读取内容,或者从Global
中拉入messageDictionary
。
我考虑扩展DefaultControllerFactory
,以便在那里构建我需要的控制器,但是我的新控制器工厂的构造函数从未被调用,尽管在Global#Application_Start
中注册了它,如
ControllerBuilder.Current.SetControllerFactory(new FooControllerFactory());
或
ControllerBuilder.Current.SetControllerFactory(typeof(FooControllerFactory));
我考虑创建一个新的IMessageDictionary
接口,以便我可以使用DI(因为我在包含不同数据的不同控制器中有不同的IDictionary<string, string>
字段),但这并不能解决构造函数中timeout
参数的问题。
我该如何解决这个问题?
为什么不创建一个IConfigurationManager
,将所有与配置相关的操作合并在一个地方,然后您可以在该管理器上包含消息和超时(并通过DI获得实例)。
我发现自定义配置类对于大多数需求来说往往是多余的。我就是这么做的,效果很好。首先,创建一个AppSettings类。
public interface IAppSettings
{
string this[string key] { get; }
}
public class AppSettings : IAppSettings
{
public string this[string key] => ConfigurationManager.AppSettings[key];
}
其次,将其注册到您的IoC容器。然后在你的控制器上,你可以只依靠IAppSettings
,得到你需要的任何东西。
public FooController(IAppSettings appSettings)
{
var mySetting = appSettings["MySetting"];
}
这也使得在单元测试中模拟配置设置非常容易。