我正在开发一个基于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
同样如此?
答案 0 :(得分:1)
您可以在注册控制器时使用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>();