Autofac 没有内置支持来根据泛型参数的类型解析泛型服务。顺便说一句,您可以使用IRegistrationSource 进行动态注册来做您想做的事情。
假设你有这些类型:
namespace A
{
interface IFoo { }
}
namespace B
{
interface IBar { }
}
interface IAdapter<T> { }
class Adapter1<T> : IAdapter<T> { }
class Adapter2<T> : IAdapter<T> { }
class Foo : A.IFoo { }
class Bar : B.IBar { }
你想要这样的东西:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().As<A.IFoo>();
builder.RegisterType<Bar>().As<B.IBar>();
builder.RegisterGeneric(typeof(Adapter1<>)).As(typeof(IAdapter<>));
builder.RegisterGeneric(typeof(Adapter2<>)).As(typeof(IAdapter<>));
IContainer container = builder.Build();
var fooAdapter = container.Resolve<IAdapter<A.IFoo>>(); // should return Adapter1<Foo>()
var barAdapter = container.Resolve<IAdapter<B.IBar>>(); // should return Adapter2<Bar>()
当Autofac 将解析IAdapter<T> 时,它无法根据T 的命名空间找到具体的实现。
IRegistrationSource 将允许您在 Autofac 需要时动态注册一个类型。
class TestRegistrationSource : 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;
}
if (!(typedService.ServiceType.IsGenericType
&& typedService.ServiceType.GetGenericTypeDefinition() == typeof(IAdapter<>)))
{
yield break;
}
Type t = typedService.ServiceType.GetGenericArguments()[0];
IComponentRegistration registration =
RegistrationBuilder.ForDelegate((c, p) => c.ResolveNamed(t.Namespace, typedService.ServiceType, p))
.As(service)
.CreateRegistration();
yield return registration;
}
}
这个IRegistrationSource 将在Autofac 需要它时注册一个新的具体实现。当 Autofac 需要 IAdapter<A.Foo> 时,它将输入 TestRegistrationSource,它将注册一个新的 IAdapter<A.Foo> 作为代表,这将解析 IAdapter<T> 的命名通用注册
为了使TestRegistrationSource 工作,您必须更改Adapter1<T> 和Adapter2<T> 的注册以使用通用命名注册。
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo>().As<A.IFoo>();
builder.RegisterType<Bar>().As<B.IBar>();
builder.RegisterSource(new TestRegistrationSource());
builder.RegisterGeneric(typeof(Adapter1<>)).Named("Namespace.A", typeof(IAdapter<>));
builder.RegisterGeneric(typeof(Adapter2<>)).Named("Namespace.B", typeof(IAdapter<>));
IContainer container = builder.Build();
var fooAdapter = container.Resolve<IAdapter<A.IFoo>>(); // will return Adapter1<Foo>()
var barAdapter = container.Resolve<IAdapter<B.IBar>>(); // will return Adapter2<Bar>()