如何在C#WebApi中将依赖项注入静态框架类

时间:2016-07-05 02:17:14

标签: c# asp.net-web-api static web-config inject

在我的用于.NET 4.6.1 WebApi项目的WebApiConfig.cs类中,我想仅在web.config中的应用程序设置设置为true时才启用CORS。我通常使用AppSettings类读取web.config AppSettings,该类将字符串中的值转换为更合适的数据类型。我声明了一个IAppSettings接口,并使用我正在使用的Autofac DI容器注册该类型。

但是,在这种情况下,WebApiConfig是一个静态类,其Register方法调用如下:GlobalConfiguration.Configure(WebApiConfig.Register); 我无法更改GlobalConfiguration.Configure类的签名,因此我没有看到如何注入IAppSettings对象以使其在Register方法中可访问。当然我可以访问ConfigurationManager,但这看起来非常h​​acky。当然我也可以将AppSettings声明为静态类,但这会使单元测试变得困难。有没有更清洁的方法来做到这一点?

以下是相关代码 - 我想通过调用appSettings类替换ConfigurationManager行:

    public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        if (System.Configuration.ConfigurationManager.AppSettings.Get("IsCorsEnabled", false))
        {
            config.EnableCors();
        }
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

非常感谢您的帮助!!

1 个答案:

答案 0 :(得分:3)

假设您的appsettings(有点类似)有这样的界面:

public interface IAppSettings
{
    T Get<T>(string name);
}

这是一个默认的实现,它只包含ConfigurationManager

public class DefaultAppSettings : IAppSettings
{
    public T Get<T>(string name)
    {
        return (T)Convert.ChangeType(ConfigurationManager.AppSettings[name], typeof(T));
    }
}

如果你然后定义一个这样的类:

public static class CurrentAppSettings
{
    public static Func<IAppSettings> Instance = () => new DefaultAppSettings();
}

您可以在注册方法中使用它:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        if (CurrentAppSettings.Instance().Get<bool>("IsCorsEnabled"))
        {
            config.EnableCors();
        }
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

如果要注入其他一些实现,比如在测试中,只需将CurrentAppSettings实例设置为其他内容:

[Test]
public void SomeTest()
{
    CurrentAppSettings.Instance = () => new SimpleKeyValueAppSettings(new Dictionary<string, string>());

    // ...
}