0

최근 MVC 4 프로젝트의 개체를 처리하기 위해 리포지토리/서비스 디자인 패턴을 채택했습니다.리포지토리 및 정적 메서드

확실히 좋은 움직임 이었지만 문제가 있음을 발견했습니다. 이제 패턴을 적용한 결과가 나올 수 있으므로 해결책을 제안 할만한 사람이 있는지 살펴 보겠습니다. 내 요구에 맞는 디자인 패턴.

사용자 지정 사용자를 처리 할 저장소와 서비스가 있습니다. 이것은 사용자 가져 오기 및 모든 사용자 방법 수행에 완벽하게 작동합니다. 하지만 Repository/Service 디자인 패턴으로 옮기기 전에 모든 사용자 관련 메서드를 처리하는 정적 클래스가있었습니다. 이러한 방법의

하나는했다 : 당신이 볼 수 있듯이

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 메서드를 처리하는 가장 좋은 방법일까요? 아니면 더 좋은 솔루션이 있습니까?

건배,

+0

이것은 저장소 또는 서비스 클래스의 코드입니까? – Oscar

+0

나는'depedency-injection'과'inversion-of-control' 태그를 보았습니다. 코드 예제에서 제공하지 않았으므로 실제로 사용합니까? –

+0

그래, 내가 내 컨트롤러와 내 서비스에 사용하지만, 코드와 함께 당신과 얼굴 싶지 않았기 때문에이 질문에 그 코드를 포함하지 않았습니다 :) – r3plica

답변

2

만약 내가 제대로 이해하고 /r3plica는, 현재의 솔루션은 귀하의 질문에 설명 된 방법을 가지고 정적 클래스 (ProfileContext)를 사용하는 것입니다.

이것은 그리 나쁘지는 않지만 일반적으로 정적 클래스는 단위 테스트에서 좋지 않기 때문에 피해야합니다.

정적 클래스를 다루는 일반적인 패턴은 래퍼입니다.

public IMembershipWrapper membershipWrapper { get; set; } 

당신이 모의를 사용할 수있는 단위 테스트의 경우 :

public interface IMembershipWrapper 
{ 
    MembershipUser GetUser(string name) 
} 

귀하의 컨트롤러는 다음 종속성 속성을 가질 것이다. 귀하의 구체적인 구현은 다음과 같을 것이다 : 당신의 경우

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

, 당신은 당신의 ProfileContext 정적 클래스에 대한 래퍼를 생성하고 사용할 수 있습니다.

+0

건배,이게 가장 좋은 해결책 같아 :) – r3plica

0

나는 비슷한 문제가있어서 그것을 해결하기 위해 서비스 싱글 톤을 만들었다. 그런 다음 한 번만 호출 할 수있는 Configure 메서드를 만들었습니다.

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; 
    } 

} 

글로벌 : 당신은 당신의 Global.asax에서 그 방법은

SecurityService.cs 파일 호출 할 수 있습니다.asax :

참고 : 전략 패턴을 사용하기 때문에 여기에 두 개의 저장소가 있습니다. 내 리포지토리 중 일부는 추가 리포지토리를 전달할 수 있으며 개체를 찾지 못하면 중첩 된 리포지토리를 호출 할 수 있습니다. 이 경우 효과는 HttpCache에 없으면 데이터베이스를 검사한다는 것입니다. 그러나 그것은 주제에서 약간 벗어났습니다.

지금, 다른 서비스에 당신은 인스턴스 메서드를 호출 할 수 있습니다

SecurityService.Instance.GetLoggedInUser(SecurityToken); 

참고 : 내 예제에서 나는 서비스 클래스에 대한 의존성 주입 만 저장소 사람을 사용하지 않는.