是否可以根据用户是否登录向控制器注入不同的服务?

Is it possible to inject different service into controller based on if user is logged in or not?

我在具有表单身份验证的 MVC4 应用程序中使用 Autofac 作为 DI 容器。我在控制器的构造函数中注入依赖于 IContext 的服务,如下所示:

public MyController(IUserService userService)
{
    this.userService = userService;
}

Autofac RegisterDependencies 方法的主体如下:

var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);

builder.RegisterType<MyDbContext>()
    .As<IContext>()
    .InstancePerRequest();
builder.RegisterType<UserService>()
    .As<IUserService>;

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

当用户登录时,IUserServiceUserService 实现被注入。现在我想对未登录的用户 IUserService 进行不同的实现:AnonymousService

有没有办法在用户未登录时通过 Autofac 注入 AnonymousService 并在用户登录时通过 UserService 注入?

我认为这种情况非常适合使用此处记录的键控服务

http://docs.autofac.org/en/latest/advanced/keyed-services.html

该服务只有两种可能的实现方式,因此您只需定义一个具有两个值的枚举:

public enum AuthenticatedStatusEnum
{
    Anonymous,
    Authenticated
}

并注册您的服务(假设是 IUserNameRetriever)两次,一次是针对每个枚举值:

builder.RegisterType<AnonymousUserNameRetriever>().Keyed<IUserNameRetriever>(AuthenticatedStatusEnum.Anonymous);
builder.RegisterType<AuthenticatedNameRetriever>().Keyed<IUserNameRetriever>(AuthenticatedStatusEnum.Authenticated);

您的控制器将以这种方式定义:

public class HomeController : Controller
{
    IUserNameRetriever _currentUserNameRetriever;

    public HomeController(IIndex<AuthenticatedStatusEnum, IUserNameRetriever> userNameRetrievers)
    {
        _currentUserNameRetriever = _userNameRetrievers[AuthenticatedStatus];
    }

    AuthenticatedStatusEnum AuthenticatedStatus
    {
        get
        {
            return System.Threading.Thread.CurrentPrincipal.Identity.IsAuthenticated ? AuthenticatedStatus.Authenticated : AuthenticatedStatus.Anonymous;
        }
    }

_currentUserNameRetriever 服务将根据用户的身份验证状态进行正确的实施。

P.S。在实际应用程序中,您通常会从另一个注入的服务中获取 AuthenticatedStatus 值。