如何在 C# WebApi 中将依赖项注入静态框架 class
How to inject a dependency into a static framework class in C# WebApi
在我的 WebApiConfig.cs class 的 .NET 4.6.1 WebApi 项目中,我只想在 web.config 中的应用程序设置设置为 true 时启用 CORS。我通常阅读 web.config AppSettings 使用 AppSettings class 将值从字符串转换为更合适的数据类型。我声明了一个 IAppSettings 接口,并向我正在使用的 Autofac DI 容器注册了该类型。
然而,在这种情况下,WebApiConfig 是一个静态的class,其Register 方法的调用方式如下:GlobalConfiguration.Configure(WebApiConfig.Register);
我无法更改 GlobalConfiguration.Configure class 的签名,因此我看不到如何注入 IAppSettings 对象以使其可在 Register 方法中访问。当然,我可以访问 ConfigurationManager,但这似乎很老套。当然,我也可以将 AppSettings 声明为静态 class,但这会使单元测试变得困难。有没有更简洁的方法来做到这一点?
这是相关代码 - ConfigurationManager 行是我想用对 appSettings 的调用替换的代码 class:
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 }
);
}
}
非常感谢您的帮助!!
假设您的应用程序设置有这样的界面(有点):
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));
}
}
如果你这样定义 class:
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>());
// ...
}
在我的 WebApiConfig.cs class 的 .NET 4.6.1 WebApi 项目中,我只想在 web.config 中的应用程序设置设置为 true 时启用 CORS。我通常阅读 web.config AppSettings 使用 AppSettings class 将值从字符串转换为更合适的数据类型。我声明了一个 IAppSettings 接口,并向我正在使用的 Autofac DI 容器注册了该类型。
然而,在这种情况下,WebApiConfig 是一个静态的class,其Register 方法的调用方式如下:GlobalConfiguration.Configure(WebApiConfig.Register); 我无法更改 GlobalConfiguration.Configure class 的签名,因此我看不到如何注入 IAppSettings 对象以使其可在 Register 方法中访问。当然,我可以访问 ConfigurationManager,但这似乎很老套。当然,我也可以将 AppSettings 声明为静态 class,但这会使单元测试变得困难。有没有更简洁的方法来做到这一点?
这是相关代码 - ConfigurationManager 行是我想用对 appSettings 的调用替换的代码 class:
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 }
);
}
}
非常感谢您的帮助!!
假设您的应用程序设置有这样的界面(有点):
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));
}
}
如果你这样定义 class:
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>());
// ...
}