我正在使用CacheManager,它使用工厂来创建实例。我不想要注册我声明的每种类型的ICacheManager,所以我正在寻找一种通过动态解析方法注册泛型类型的方法。使用Ninject,我可以这样做:
kernel
.Bind(typeof(ICacheManager<>))
.ToMethod((context) => CacheFactory.FromConfiguration(context.GenericArguments[0], "defaultCache"))
.InSingletonScope();
其中context.GenericArguments [0]将是我的泛型的类型。例如,来自
的对象ICacheManager<object> cache;
如何使用Autofac做这样的事情?
修改
根据Cyril的回答制作IRegistrationSource。 SingleInstance是必需的,因为CacheManager预先设置了具有CacheManager实例id的密钥。
public class CacheManagerRegistrationSource : IRegistrationSource
{
public Boolean IsAdapterForIndividualComponents
{
get
{
return false;
}
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
IServiceWithType typedService = service as IServiceWithType;
if (typedService == null || !typedService.ServiceType.IsGenericType)
{
yield break;
}
Type cacheManagerType = typedService.ServiceType;
if (cacheManagerType.GetGenericTypeDefinition() != typeof(ICacheManager<>))
{
yield break;
}
IComponentRegistration registration = (IComponentRegistration)RegistrationBuilder.ForDelegate(cacheManagerType, (c, p) =>
{
return CacheFactory.FromConfiguration(cacheManagerType.GetGenericArguments()[0], "defaultCache");
})
.SingleInstance()
.CreateRegistration();
yield return registration;
}
}
答案 0 :(得分:2)
默认情况下, Autofac 不允许检索正在注册的对象的通用类型。没有简单的内置方法可以执行此操作,但您可以使用IRegistrationSource
来实现您的目标:
public class CacheManagerRegistrationSource : IRegistrationSource
{
public Boolean IsAdapterForIndividualComponents
{
get
{
return false;
}
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
IServiceWithType typedService = service as IServiceWithType;
if (typedService == null)
{
yield break;
}
Type cacheManagerType = typedService.ServiceType
.GetInterfaces()
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICacheManager<>))
.FirstOrDefault();
if (cacheManagerType == null)
{
yield break;
}
IComponentRegistration registration =
RegistrationBuilder.ForDelegate(cacheManagerType, (c, p) => {
return CacheFactory.FromConfiguration(cacheManagerType.GetGenericArguments()[0], "defaultCache");
})
.SingleInstance()
.CreateRegistration();
yield return registration;
}
}
然后你必须通过以下方式注册注册来源:
builder.RegisterSource(new CacheManagerRegistrationSource());
这是RegisterGeneric
方法在内部工作的方式。
答案 1 :(得分:0)
很糟糕,但你可以做到以下几点:
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(ICacheManager<>))
.OnActivating(e =>
{
var instance = typeof(CacheFactory).GetMethod("FromConfiguration").MakeGenericMethod
e.Instance.GetType().GenericTypeArguments[0])
.Invoke(null, new object[] { "..." });
e.ReplaceInstance(instance);
});