如何在Startup类中替换ServiceLocator

时间:2014-08-21 18:20:31

标签: c# asp.net-web-api oauth unity-container owin

我使用Owin(OAuth),ASP.NET WebApi2和Unity以及基于OAuthAuthorizationServerProvider的自定义授权服务器提供程序(SimpleAuthorizationServerProvider),但使用了我的工作单元和存储库模式。 我的问题是解决Startup类中的依赖关系,我的意思是Startup类需要SimpleAuthorizationServerProvider而SimpleAuthorizationServerProvider需要IUserOrchestration和IUnitOfWorkFactory。 SimpleAuthorizationServerProvider中的依赖关系很好,问题出在Startup类中,因为Startup类必须有没有参数的构造函数,并且属性注入不起作用 - 依赖注入太晚了。 只有工作解决方案基于ServiceLocator,老实说,这是个坏主意。 我需要找到另一个有效的解决方案......

public class Startup
{
    private SimpleAuthorizationServerProvider _simpleProvider;

    public void Configuration(IAppBuilder app)
    {
        HttpConfiguration config = new HttpConfiguration();

        // Create instance for Unity container - let's try to run!
        var container = new UnityContainer();
        config.DependencyResolver = new UnityResolver(container);

        // Include project classes to IoC container
        new CommonUnityConfiguration().Configurate(container);
        new RepositoryUnityConfiguration().Configurate(container);
        new OrchestrationUnityConfiguration().Configurate(container);
        new ServerUnityConfiguration().Configurate(container);

        // HERE COMES PROBLEMATIC LINE
        _simpleProvider = container.Resolve<SimpleAuthorizationServerProvider>(); // Ugh! ServiceLocator - not pretty, but how can I replace it? :(

        ConfigureOAuth(app);
        WebApiConfig.Register(config);
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); // enable CORS
        app.UseWebApi(config);
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = _simpleProvider
        };

        // Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
        app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
}

和SimpleAuthorizationServerProvider的实现:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private readonly IUserOrchestration _userOrchestration;
    private readonly IUnitOfWorkFactory _unitOfWorkFactory;

    public SimpleAuthorizationServerProvider(IUserOrchestration userOrchestration, IUnitOfWorkFactory unitOfWorkFactory)
    {
        _userOrchestration = userOrchestration;
        _unitOfWorkFactory = unitOfWorkFactory;
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        using (IUnitOfWork uow = _unitOfWorkFactory.Create())
        {
            var user = _userOrchestration.FindUser(context.UserName);
            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
        }

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);
    }
}

1 个答案:

答案 0 :(得分:0)

我没有在那里看到服务定位器,而是看起来像一个组合根。

虽然组合根是否是一个解决依赖关系并使用它们或仅配置它们的地方是有争议的,但我想知道你在哪里使用已解析的实例 - 在代码片段中,实例已被解析并且从未使用过(! ?)。

您可以重构它以将其拆分为两个不同职责的类 - 具有干净的组合根,您只需配置其他初始化类,您实际使用该配置。或者更确切地说,决定您希望启动类应该是哪两个。