2016-08-15 41 views
0

我有一个Web API控制器FooController,看起来像具体类型的Web API的控制器构造

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文件中使用自定义配置部分,它由Global.asax文件看起来像这样在阅读了messageDictionary

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,但对于我的新控制器工厂构造从来没有所谓,尽管像

ControllerBuilder.Current.SetControllerFactory(new FooControllerFactory()); 

ControllerBuilder.Current.SetControllerFactory(typeof(FooControllerFactory)); 
Global#Application_Start对其进行注册

我考虑制作一个新的IMessageDictionary接口,以便我可以使用DI(因为我在不同控制器中有不同的IDictionary<string, string>字段包含不同的数据),但t帽子并没有解决构造函数中参数timeout的问题。

我该如何解决这个问题?

+0

您可以注入一个服务接口,为您的控制器执行此项工作。我不确定这是否真的会改善您的设计。 – Noppey

+0

注入一个'ITimeoutProvider'并为其创建一些简单的实现并将其注册到DI服务中。如果你不使用DI,那么考虑一个像AutoFac这样的框架。 – Igor

回答

0

为什么不创建一个IConfigurationManager将所有配置相关的操作合并到一个地方,然后您可以在该管理器中包含消息和超时(并通过DI获取实例)。

0

我发现自定义配置类往往是矫枉过正的大多数需求。这就是我所做的,它很棒。首先,创建一个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"]; 
} 

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