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

时间:2015-04-18 23:28:13

标签: c# asp.net-mvc-4 dependency-injection forms-authentication autofac

我在使用表单身份验证的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));

当用户登录时,会注入UserService IUserService的实现。现在,我希望为未登录的用户IUserService实现不同的AnonymousService实现:AnonymousService

如果用户未登录,是否可以通过Autofac注入UserService,如果用户已登录,是否有{{1}}?

1 个答案:

答案 0 :(得分:3)

我认为这种情况是使用此处记录的密钥服务的理想选择

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

您只有两种可能的服务实现,因此您只需要定义两个值枚举:

public enum AuthenticatedStatusEnum
{
    Anonymous,
    Authenticated
}

并注册您的服务(让我们说IUserNameRetriever)两次,一次为foreach枚举值:

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值。