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参数的问题。

我该如何解决这个问题?

Web API控制器构造函数中的具体类型

为什么不创建一个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"];
}

这也使得在单元测试中模拟配置设置非常容易。