2015-06-27 6 views
6

Chcę utworzyć usługę pamięci podręcznej, która otrzyma regularną usługę jako parametr konstruktora. Następnie, gdy klucz pamięci podręcznej nie istnieje, chcę wywołać zwykłą usługę i zaktualizować pamięć podręczną. Moim pomysłem jest posiadanie tego samego interfejsu w zwykłej usłudze usługi i pamięci podręcznej. Ale kiedy próbuję wstrzyknąć implementację usługi buforowania i wykonać metodę otrzymuję wyjątek:Wpisz bezpośrednio lub pośrednio w zależności od siebie Prosty wtryskiwacz

Zarejestrowany przedstawiciel dla typu IUserRepository zgłosił wyjątek. Konfiguracja jest nieprawidłowa. Typ CacheUserRepository jest bezpośrednio lub pośrednio zależny od niego samego.

Mój kod:

public interface IUserRepository 
{ 
    UserDTO Get(int userId); 
} 

public class UserRepository : IUserRepository 
{ 
    public virtual UserDTO Get(int userId) 
    { 
      return new UserDTO() { Id = 1, Age = 28, Name = "Emil" }; 
    } 
}  

Oto mój repozytorium cache:

public class CacheUserRepository : IUserRepository 
{ 
    private readonly IUserRepository _userRepository; 
    private readonly ICache _cache; 

    public CacheUserRepository(IUserRepository userRepository, ICache cache) 
    { 
      _userRepository = userRepository; 
      _cache = cache; 
    } 

    public DTO.UserDTO Get(int userId) 
    { 
      var userKey = "User_" + userId.ToString(); 

      UserDTO val = _cache.Get<UserDTO>(userKey); 

      if (val != null) 
        return val; 

      UserDTO user = _userRepository.Get(userId); 
      _cache.Add(userKey, user); 

      return user; 
    } 
} 

Oto mój główny skład:

public class ExecutionClass 
{ 
    private readonly Container _container; 

    public ExecutionClass() 
    { 
     _container = new Container(); 

     _container.Register<IUserRepository, CacheUserRepository>(); 
     _container.Register<ICache, Cache>(); 
    } 

    public UserDTO GetUser(int Id) 
    { 
     //throws: The type CacheUserRepository is directly or indirectly depending 
     // on itself. 
     var userRepo = _container.GetInstance<IUserRepository>(); \ 
     return userRepo.Get(Id); 
    } 
} 
+2

Musisz użyć metody RegisterDecorator, aby zarejestrować CacheUserRepository – qujck

Odpowiedz

7

Co się dzieje, jest następujące: Użytkownik zarejestrowany klasę CacheUserRepository według rodzaju usługi IUserRepository. Oznacza to, że za każdym razem, gdy ktoś poprosi o numer IUserRepository (przez wywołanie GetInstance<IUserRepository>() lub wymagając IUserRepository jako argumentu konstruktora), Simple Injector dostarczy mu nową instancję CacheUserRepository.

Do tej pory tak dobrze, ale sama CacheUserRepository zawiera argument konstruktora z IUserRepository. Spowoduje to, że Simple Injector dostarczy swoją CacheUserRepository z nową instancją CacheUserRepository. I oczywiście ta nowa instancja zostanie ponownie dostarczona z nową instancją CacheUserRepository. Ponieważ spowoduje to wyjątek stackoverflow, Simple Injector zapobiega temu i rzuca wyjątek, który zobaczyłeś.

Twoja CacheUserRepository jest w rzeczywistości dekoratorem. Simple Injector obsługuje obsługę dekoratorów. W ten sposób Twoja rejestracja powinna wyglądać następująco:

container.Register<IUserRepository, UserRepository>(); 
container.RegisterDecorator<IUserRepository, CacheUserRepository>(); 

Sposób RegisterDecorator zwraca szczególną uwagę na zależność cykliczną i upewnić się, że nie będzie prosty Injector gonić własny ogon.

+0

To działa dla mnie. Dzięki za pomoc. – Emil

Powiązane problemy