服务定位器模式和登录用户

本文关键字:登录 用户 模式 定位器 服务 | 更新日期: 2023-09-27 17:54:53

我正在调整我的web应用程序层,以使代码更易于测试。

当前UI与传入接口的服务定位器对话,这将根据该类型返回适当的对象:

ServiceLocator.Get<ISomeService>().ListStuff(arg1, arg2);

在内部,服务使用IServiceContext的实例实例化并缓存。

private static Lazy<IDictionary<Type, object>> _services = new Lazy<IDictionary<Type, object>>(GetServices);
public interface IServiceContext
{
    IConfiguration Configuration { get; }
    IUser CurrentUser { get; internal set; }
    ILogProvider Log { get; }
    ICacheProvider Cache { get; }
    IProfilerProvider Profiler { get; }
}
public LogService(IServiceContext serviceContext)
  : base(serviceContext) { }

我对这个概念很满意,它看起来足够坚固,我唯一的问题是我想让当前登录的用户在ServiceContext中可用,但不确定实现它的最佳方法。

我的思绪在这些可能的选择中穿梭:

  1. ServiceLocator中保持一个简单的方法,该方法处理获取用户会话并将其注入服务,因为请求他们进来。
  2. 将获取当前用户从IServiceContext移到每个服务的ServiceBase基类中。
  3. 停止这样做,让每个需要用户的服务依赖于它。

我感谢任何建议,我明白这个问题不符合网站的真正精神。我已经试错了4天才得出这个结论,只需要解开这个谜题的最后一块。

服务定位器模式和登录用户

可能有很多解决方案,我不完全确定我理解你的问题,但我会尽力帮助你。

每当我需要当前用户时,我就在使用它的代码上下文中调用静态实用程序类。这样我就消除了陈旧信息的可能性。

你可以创建一个实现IUser的类,比如

class User : IUser {
  private System.Security.Principal.WindowsIdentity identity;
  public User() {
    this.identity = identity = System.Security.Principal.WindowsIdentity.GetCurrent();
  }
  public string UserName { get { return this.identity.Name; } }
}

然后可能是:

public class ServiceContext : IServiceContext
{
    IUser CurrentUser { get { return new User(); } }
}