我正在开发基于ASP.NET Core的Web应用程序,并且正在使用Autofac进行依赖项注入。
我有一个ICacheProvider
接口,该接口有3个具体实现-OrderCacheProvider
,ProductsCacheProvider
和CustomerCacheProvider
。不同的缓存提供程序的基础结构和逻辑是不同的。它们的注册如下:
builder.RegisterType<CustomerCacheProvider>()
.Keyed<ICacheProvider>(CacheType.Customer);
builder.RegisterType<OrderCacheProvider>()
.Keyed<ICacheProvider>(CacheType.Order);
builder.RegisterType<ProductCacheProvider>()
.Keyed<ICacheProvider>(CacheType.Product);
现在我有3个控制器-
OrdersController
,ProductsController
和CustomerController
。每个控制器均以以下方式期望ICacheProvider
public class OrdersController: BaseController {
private readonly ICacheProvider _cacheProvider;
public OrdersController(ICacheProvider cacheProvider) {
_cacheProvider = cacheProvider;
}
}
现在我的问题是如何在
OrderCacheProvider
中注入OrdersController
? CustomerCacheProvder
到CustomersController
和ProductsCacheProvider
也是一样吗? 最佳答案
注册控制器时,可以使用WithParameter
方法来指定应使用的ICacheProvider
builder.RegisterType<OrdersController>()
.WithParameter(ResolvedParameter.ForKeyed<ICacheProvider>(CacheType.Order));
另一种选择是使用
KeyFilter
属性public class OrdersController
{
public OrdersController([KeyFilter(CacheType.Order)]ICacheProvider cacheProvider)
{ }
}
我更喜欢第一个解决方案,而不是看起来更纯净的解决方案,您的组件只需要请求
ICacheProvider
即可。另一个解决方案是创建一个自定义模块,该模块将基于约定为每个控制器添加参数。
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry, IComponentRegistration registration)
{
base.AttachToComponentRegistration(componentRegistry, registration);
if (registration.Activator.LimitType.IsSubclassOf(typeof(BaseController)))
{
String controllerName = registration.Activator.LimitType.Name;
controllerName = controllerName.Substring(0, controllerName.Length - 10);
if (Enum.TryParse<CacheType>(controllerName, out CacheType cacheType))
{
registration.Preparing += (sender, e) =>
{
e.Parameters = new Parameter[]
{
ResolvedParameter.ForKeyed<ICacheProvider>(cacheType)
}
.Concat(e.Parameters);
};
}
else
{
// throw, use default cache, do nothing, etc.
throw new Exception($"No cache found for controller {controllerName}");
}
}
}
}
它是更多的代码,但是您不必在每次控制器注册时都使用
WithParameter
,如果您有很多控制器,那就很棒。您仍然必须注册模块:builder.RegisterModule<CacheProviderModule>();