I have been trying to register and inject two different objects of the same type using autofac, but I am unable to get the second object injected successfully. The second object injected is always either the same instance of type 1 registered first when using SingleInstance() or another instance of type 1 when InstancePerLifetimeScope is used. InstancePerDependency doesn't work either. Any suggestions on how this can be achieved? Thanks!
Found a similar unsolved question - Inject multiple instances of same type - Autofac
/* Register named object of type1 */
builder.RegisterType<TestClient>()
.As<TestClient>()
.UsingConstructor(typeof(Settings), typeof(SampleEnum))
.WithParameters(new[]{
new ResolvedParameter((p, c) => p.ParameterType.IsAssignableTo<Settings>(), (p, c) => c.Resolve<Settings>()),
new ResolvedParameter((p, c) => p.ParameterType == typeof(SampleEnum) && p.Name == "eventtype",(p, c) => SampleEnum.Type1),
}).Named<TestClient>(clientoftype1).InstancePerDependency();
/* Register named object of type2 */
builder.RegisterType<TestClient>()
.As<TestClient>()
.UsingConstructor(typeof(Settings), typeof(SampleEnum))
.WithParameters(new[]{
new ResolvedParameter((p, c) => p.ParameterType.IsAssignableTo<Settings>(), (p, c) => c.Resolve<Settings>()),
new ResolvedParameter((p, c) => p.ParameterType == typeof(SampleEnum) && p.Name == "eventtype",(p, c) => SampleEnum.Type2),
}).Named<TestClient>(clientoftype2)).InstancePerDependency();
/*Controller registration
public DevController(TestClient clientoftype1, TestClient clientoftype2)
{..}
*/
builder
.RegisterType<DevController>()
.As<DevController>()
.WithParameters(new []{
ResolvedParameter.ForNamed<TestClient>("clientoftype1"),
ResolvedParameter.ForNamed<TestClient>("clientoftype2"),
} ).InstancePerRequest();
/*Check registered types*/
var types = container.ComponentRegistry.Registrations
.Where(r => typeof(TestClient).IsAssignableFrom(r.Activator.LimitType))
.Select(r => r.Activator.LimitType);
var countofobjects = types.ToList();//This has 2 objects.
Generally speaking what you're doing - requiring more than one of the same type in the constructor but as separate parameters is sort of a dependency injection no-no. That is, this is generally something to avoid doing:
The reason for that is that DI, as you've found, primarily works on type-based injection. This isn't unique to .NET or Autofac, that's just how it is. From a design perspective, I'd probably ask why you don't, instead, do something like...
I'd ask that because if you can't treat the two dependencies the same it's sort of a violation of the Liskov substitution principle and you'd actually want to have different interfaces (even if they look the same) to differentiate the two things.
However, assuming you can't redesign things, you can use named services along with the
KeyFilterAttributeto get what you want.Here's a complete, minimal console app showing how it works.
When you run this, you'll get two different IDs, like:
If you were to remove the filter attributes then you'd get the same ID because, as you saw, injecting by type will end up with the same instance each time - last in wins. The filtering is the magic that makes it work.