【问题标题】:How to inject service in custom ClaimsPrincipal using Simple Injector如何使用 Simple Injector 在自定义 ClaimsPrincipal 中注入服务
【发布时间】:2015-02-12 01:23:55
【问题描述】:

我正在开发一个使用 ADFS 进行身份验证并使用 SimpleInjector 作为 IoC 容器的 ASP.Net MVC 项目。应用程序的服务层位于不同的项目中,服务在启动时注入到控制器构造函数中。其中一项服务是用户服务,我想用它来从我的数据层获取用户信息等。

我有一个自定义 Principal(继承自 ClaimsPrincipal),我想在其上使用此用户服务并在其中存储用户信息。我面临的问题是我不确定如何“粘合" 自定义主体的用户服务。

我尝试在每次身份验证后获取用户服务的实例并将其注入身份,但我收到错误消息,指出容器不包含服务实例。我的代码如下:

Application_Start()

    protected void Application_Start()
    {
        // Register the IoC container
        InjectorConfig.RegisterDependencies(_container);

        // RouteConfig etc...
    }

InjectorConfig

public class InjectorConfig
{
    /// <summary>
    /// Create the IoC container and register all dependencies
    /// </summary>
    public static void RegisterDependencies(Container container)
    {
        // Create the IoC container
        //var container = new Container();

        // Get the assembly that houses the services
        var serviceAssembly = typeof (UserService).Assembly;

        // Interate through the assembly and find all the services 
        var registrations = (
            from type in serviceAssembly.GetExportedTypes()
            where type.Namespace == "MyApp.Services"
            where type.GetInterfaces().Any()
            select new
            {
                Service = type.GetInterfaces().Single(), 
                Implementation = type,
            });

        // Register each of the services
        foreach (var registration in registrations)
        {
            container.Register(registration.Service, registration.Implementation, Lifestyle.Transient);
        }

        // Verify the container and set the MVC dependency resolver
        container.Verify();
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    }
}

我的自定义ClaimsPrincipal

public class MyCustomPrincipal : ClaimsPrincipal
{
    private readonly IUserService _userService;

    public MyCustomPrincipal(IIdentity identity, IUserService userService)
        :base(identity)
    {
        this._userService = userService;
    }

    public override bool IsInRole(string role)
    {
        return this._userService.IsInRole(this.Identity.GetUserId(), role);
    }
}

我的用户服务在不同的程序集

public class UserService : IUserService
{
    public bool IsInRole(string currentUserId, string roleName)
    {
        // Check roles here
        return true;
    }
}

Application_PostAuthenticateRequest()

这是发生错误的地方。没有可用的实例

    protected void Application_PostAuthenticateRequest()
    {
        var currentUser = ClaimsPrincipal.Current.Identity;

        // This is where the error occurs. No instance available
        var userService = this._container.GetInstance<IUserService>();
        HttpContext.Current.User = new MyCustomPrincipal(currentUser, userService);
    }

我有点像 IoC 新手,所以可能有一个简单的解决方案,但我正在努力解决这个问题(形象地说)。

您能提供的任何帮助将不胜感激!

更新 这是异常详细信息

SimpleInjector.ActivationException was unhandled by user code
  HResult=-2146233088
  Message=No registration for type IUserService could be found.
  Source=SimpleInjector
  StackTrace:
       at SimpleInjector.Container.ThrowMissingInstanceProducerException(Type serviceType)
       at SimpleInjector.Container.GetInstanceFromProducer(InstanceProducer instanceProducer, Type serviceType)
       at SimpleInjector.Container.GetInstanceForType[TService]()
       at SimpleInjector.Container.GetInstance[TService]()
       at MyWebApp.Web.MvcApplication.Application_PostAuthenticateRequest() in c:\Projects\MyWebApp\Client\\MyWebApp.Web\Global.asax.cs:line 46
  InnerException: 

【问题讨论】:

  • 您遇到的错误究竟是什么?你能发布完整的异常、消息和堆栈跟踪吗?
  • 嗨@Steven,感谢您的回复。我已经用堆栈跟踪更新了这个问题。
  • 嗯,信息很清楚。你确定这是同一个容器吗?您可以在调试器中查看容器的注册情况。也许您的 RegisterDependencies 没有被调用,或者您在调用之后创建了一个新容器。

标签: c# asp.net-mvc dependency-injection adfs simple-injector


【解决方案1】:

我能想到的可能原因有 5 个:

  1. UserService 类未实现 IUserService。
  2. UserService 类不在命名空间“MyApp.Services”中。
  3. 类是内部的。
  4. 您不小心创建了第二个(空)容器。
  5. 在调用 RegisterDependencies 之前调用 PostAuthentication 方法。

【讨论】:

  • 感谢您的帮助@Steven。我最终用var userService = DependencyResolver.Current.GetService&lt;IUserService&gt;(); 解决了这个问题
  • @Andrew 如果这样可以解决问题,那么必须有第二个容器实例。您应该真正找到发生这种情况的原因,因为它可能会在此过程中造成更多麻烦。
猜你喜欢
  • 2018-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多