0

最近我采用了存储库/服务设计模式来处理我的 MVC 4 项目中的对象。

这绝对是一个很好的举措,但我发现了一个问题 :) 现在这可能取决于我对模式的应用,所以我想我会把它放在那里,看看是否有人可以提出适合的解决方案或设计模式我的需要。

我有一个存储库和一个服务来处理自定义用户。这非常适合获取用户和执行任何用户方法。但是,在我转向存储库/服务设计模式之前,我有一个静态类来处理所有与用户相关的方法。

其中一种方法是:

public static Profile CurrentUser()
{
    // TODO: Need to replace the Profile session when any permissions are changed....
    var companyId = HttpContext.Current.Session["CompanyId"].ToString();

    if (HttpContext.Current.User.Identity.IsAuthenticated && !string.IsNullOrEmpty(companyId))
    {
        var userId = Membership.GetUser(HttpContext.Current.User.Identity.Name).ProviderUserKey.ToString();
        var repository = new ProfileRepository(companyId);

        return repository.Get(userId);
    }
    else
        return null;
}

如您所见,如果特定用户已登录,此方法将返回他们的个人资料。如果未登录,则返回 null。

我的问题是该方法需要与服务和存储库分开,因为必须从任何控制器调用它,这就是我将其设为静态的原因。

为了解决这个问题,我创建了一个名为 ProfileContext 的类,而 CurrentUser() 是这个静态类中唯一的方法。

所以我的问题很简单。这将是处理 CurrentUser 方法的最佳方式,还是有另一种更好的解决方案?

干杯,/r3plica

4

2 回答 2

2

如果我理解正确,您当前的解决方案是使用ProfileContext具有您问题中概述的方法的静态类 ( )。

这并不算太糟糕,但通常最好避免使用静态类,因为它们在单元测试中确实不适合。

处理静态类的一般模式是包装器。

例如

public interface IMembershipWrapper
{
    MembershipUser GetUser(string name)
}

然后,您的控制器将具有依赖属性:

public IMembershipWrapper membershipWrapper { get; set; }

对于单元测试,您可以使用 Mock。您的具体实现如下所示:

public class MembershipWrapper : IMembershipWrapper
{
    public MembershipUser GetUser(string name) 
    {
        return Membership.GetUser(string);
    }
}

在您的情况下,您可以为您的ProfileContext静态类创建一个包装器并使用它。

于 2013-08-28T13:46:36.837 回答
0

我有一个类似的问题,为了解决它,我做了一些服务单例。然后我做了一个只能调用一次的配置方法。然后您可以在 global.asax 文件中调用该方法

安全服务.cs:

public sealed class SecurityService {
    private ISecurityRepository _repository;
    public static SecurityService Instance { get; private set; }

    private SecurityService(ISecurityRepository repository) {
        _repository = repository;
    }

    public static void Configure(ISecurityRepository repository) {
        Instance = new SecurityService(repository);
    }


    public Model.LoginResponse GetUser(Model.UserRequest request) {
        if (string.IsNullOrEmpty(request.SecurityToken)) return null;
        User user = _repository.GetUserByToken(request.SecurityToken);
        if (user == null) throw new HabitationException("Invalid Security Token. Please login.", null);
        return AutoMapper.Mapper.Map<Model.LoginResponse>(user);
    }


    public Model.LoginResponse Login(Model.LoginRequest request) {
        string strPassword = EncryptPassword.GetMd5Hash(request.Password);
        User user = _repository.GetUser(request.Username, strPassword);
        return AutoMapper.Mapper.Map<Model.LoginResponse>(user);
    }

    internal User GetLoggedInUser(string securityToken) {
        if (string.IsNullOrEmpty(securityToken)) {
            return null;
        }

        User user = _repository.GetUserByToken(securityToken);
        if (user == null) throw new HabitationException("Invalid Security Token.", null);
        return user;
    }

}

全球.asax:

protected void Application_Start() {
        MyProject.LinqToSQL.Repositories.SecurityRepository securityRepository = new MyProject.Repository.LinqToSQL.Repositories.SecurityRepository(connection);
        MyProject.Repository.HttpCache.Repositories.SecurityRepository securityCacheRepository = new MyProject.Repository.HttpCache.Repositories.SecurityRepository(securityRepository);
        MyProject.Domain.Service.Interface.SecurityService.Configure(securityCacheRepository);
}

注意:这里有两个存储库,因为我使用的是策略模式。我的一些存储库可以传递额外的存储库,如果他们没有找到对象,他们可以调用嵌套存储库。在这种情况下,效果是如果它不在 HttpCache 中,它会检查数据库。但这有点跑题了。

现在,在另一个服务中,您可以调用任何实例方法:

    SecurityService.Instance.GetLoggedInUser(SecurityToken);

注意:在我的示例中,我没有对服务类使用依赖注入,仅对存储库使用依赖注入。

于 2015-03-26T22:27:53.930 回答