I have an IoCConfig
where in the RegisterDependencies method first all Services
(same assembly as ServiceBase
) are registered, except for one service and one class called LastActivityUpdator
and a decorator of this class called AnonymousUserLastActivityUpdator
which both implement ILastActivityUpdator
.
The goals I want to accomplish is to have the decorator registered properly, which already works following this answer. And I also asked for a way to for one class (UserService
) use the LastActivityUpdator
and for another (AnonymousUserService
) use the AnonymousUserLastActivityUpdator
, which was answered here. To be complete (I don't think it is relevant to this problem), I am using a keyed service following this answer to decide which class is injected in other times.
Unfortunately, when I combine the ideas I always see an AnonymousUserLastActivityUpdator
injected, also in the case of UserService
where I want a LastActivityUpdator
to be provided.
Below you'' find the IocConfig
which uses both the idea to register the decorator and to provide specific classes with one type:
builder.RegisterAssemblyTypes(typeof(ServiceBase).Assembly)
.Except<AnonymousUserService>()
.Except<LastActivityUpdator>()
.Except<AnonymousUserLastActivityUpdator>()
.AsImplementedInterfaces()
.InstancePerRequest();
builder.RegisterType<LastActivityUpdator>()
.Named<ILastActivityUpdator>("lastActivityUpdator");
builder.RegisterType<AnonymousUserLastActivityUpdator>()
.Named<ILastActivityUpdator>("anonymousUserLastActivityUpdator");
builder.RegisterDecorator<ILastActivityUpdator>(
(c, inner) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator",
TypedParameter.From(inner)),
fromKey: "lastActivityUpdator")
.As<ILastActivityUpdator>();
builder.Register(c => new UserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.Resolve<ILastActivityUpdator>()));
builder.Register(c => new AnonymousUserService(
c.Resolve<OogstplannerUnitOfWork>(),
c.Resolve<CookieProvider>(),
c.Resolve<AnonymousUserLastActivityUpdator>()));
builder.RegisterType<AnonymousUserService>()
.Keyed<IUserService>(AuthenticatedStatus.Anonymous)
.InstancePerRequest();
builder.RegisterType<UserService>()
.Keyed<IUserService>(AuthenticatedStatus.Authenticated)
.InstancePerRequest();
Unfortunately this does not work. Both the AnonymousUserService
and the UserService
get an instance of the LastActivityUpdator
, while I want AnonymousUserService
to get an instance of the AnonymousUserService
.
Does anyone know why my RegisterDependencies method does not provide the LastActivityUpdator
to UserService
and how I can accomplish this?
/edit
Using the answer of Cyril and some adjustments the registering works for the UserService
, but once the user logs out and a AnonymousUserService
is used I get the error:
Circular component dependency detected:
Services.AnonymousUserService ->
Services.AnonymousUserService ->
Services.AnonymousUserLastActivityUpdator ->
Services.AnonymousUserLastActivityUpdator -> System.Object ->
Services.AnonymousUserLastActivityUpdator
I adjusted the code somewhat of Cyril's answer (fixed some typos and switched the anonymous- and normal UserService) and I might have made a mistake, here it is:
builder.RegisterAssemblyTypes(typeof(ServiceBase).Assembly)
.Except<AnonymousUserService>()
.Except<LastActivityUpdator>()
.Except<AnonymousUserLastActivityUpdator>()
.AsImplementedInterfaces()
.InstancePerRequest();
builder.RegisterType<LastActivityUpdator>()
.Named<ILastActivityUpdator>("lastActivityUpdator");
builder.RegisterType<AnonymousUserLastActivityUpdator>()
.Named<ILastActivityUpdator>("anonymousUserLastActivityUpdator");
builder.RegisterDecorator<ILastActivityUpdator>(
(c, inner) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator",
TypedParameter.From(inner)),
fromKey: "lastActivityUpdator")
.As<ILastActivityUpdator>();
builder.RegisterType<UserService>()
.Keyed<IUserService>(AuthenticatedStatus.Authenticated)
.WithParameter(
(p, c) => p.Name == "lastActivityUpdator",
(p, c) => c.ResolveNamed<ILastActivityUpdator>("lastActivityUpdator"))
.InstancePerRequest();
builder.RegisterType<AnonymousUserService>()
.Keyed<IUserService>(AuthenticatedStatus.Anonymous)
.WithParameter(
(p, c) => p.Name == "anonymousUserLastActivityUpdator",
(p, c) => c.ResolveNamed<ILastActivityUpdator>("anonymousUserLastActivityUpdator"))
.InstancePerRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
You have 2 kind of registrations for
UserService
andAnonymousUserService
.In the first solution you register
AnonymousUserService
by explicitly calling the constructor and by asking Autofac to resolve aAnonymousUserLastActivityUpdator
but there is no registration for this service. Instead of resolving this type, you can resolve a namedILastActivityUpdator
The second registration is a
Keyed
but you don't specify that theAnonymousUserService
should use aanonymousUserLastActivityUpdater
you could do it by using theWithParameter
methodYou don't have to have both registration, the last one should be enough for your scenario.