Reputation: 1542
I'm a new user of Autofac.
I have a factorythat needs to create a different class based on the input to the factory method, but only one of the classes that needs to be created has other dependencies.
I found this answer: Autofac Binding at Runtime
whose solution worked well.
but then I started reading about Autofac's delegate factories (http://docs.autofac.org/en/latest/advanced/delegate-factories.html)... and now I'm confused.
It appears, if you use a delegate factory, then you don't actually have to write a factory class at all?
Here is a snipped from my current factory class:
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
private readonly IComponentContext autofacContainer;
public ExternalUserInformationProviderFactory(IComponentContext autofacContainer)
{
this.autofacContainer = autofacContainer;
}
public IProvideExternalUserInformation GetExternalUserInformationProvider(string loginProvider)
{
switch (loginProvider)
{
case "Google":
return autofacContainer.Resolve<GoogleExternalUserInformationProvider>();
case "Twitter":
return autofacContainer.Resolve<TwitterExternalUserInformationProvider>();
}
return null;
}
}
In this example, the TwitterExternalUserInformationProvider takes a dependency in its constructor:
public class TwitterExternalUserInformationProvider : IProvideExternalUserInformation
{
private readonly ITwitterRepository twitterRepository;
public TwitterExternalUserInformationProvider(ITwitterRepository twitterRepository)
{
this.twitterRepository = twitterRepository;
}
}
and the GoogleExternalUserInformationProvider takes no constructor args at all.
here is how I have this factory wired up in Startup.cs (I'm using asp.net core):
var containerBuilder = new ContainerBuilder();
containerBuilder.Register<IExternalUserInformationProviderFactory>(c => new ExternalUserInformationProviderFactory(c.Resolve<IComponentContext>()));
containerBuilder.RegisterType<TwitterExternalUserInformationProvider>();
containerBuilder.RegisterType<GoogleExternalUserInformationProvider>();
Autofac is smart enough to resolve the ITwitterRepository dependency for me, which is really cool.
Based on this current implementation, is it possible for me to use a delegate factory and get rid of the ExternalUserInformationProviderFactory altogether?
I'm curious.
Thanks
Upvotes: 0
Views: 1215
Reputation: 16187
Delegate factory won't choose between 2 implementations of a service, it will only create a component based on its dependencies.
In your case you need a factory. Instead of depend on IComponentContext
, your factory may also depend on IIndex<String, IProvideExternalUserInformation>
which may avoid issue with scope & co.
Your ExternalUserInformationProviderFactory
could look like this :
public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
public ExternalUserInformationProviderFactory(IIndex<String, IProvideExternalUserInformation> providers)
{
this._providers = providers;
}
private readonly IIndex<String, IProvideExternalUserInformation> _providers;
public IProvideExternalUserInformation GetExternalUserInformationProvider(String loginProvider)
{
IProvideExternalUserInformation provider;
if (!this._providers.TryGetValue(loginProvider, out provider))
{
throw new Exception("boom");
}
return provider;
}
}
and your registration :
builder.RegisterType<TwitterExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("twitter");
builder.RegisterType<GoogleExternalUserInformationProvider>()
.Named<IProvideExternalUserInformation>("google");
builder.RegisterType<ExternalUserInformationProviderFactory>()
.As<IExternalUserInformationProviderFactory>();
Upvotes: 1