根据自身的简单注入器直接或间接输入

Emi*_*mil 9 .net c# dependency-injection simple-injector

我想创建Cache服务,它将常规服务作为构造函数参数.然后,当缓存键不存在时,我想调用常规服务并更新缓存.我的想法是在常规服务和缓存服务中使用相同的界面.但是,当我尝试注入缓存服务实现和执行方法时,我得到异常:

类型IUserRepository的已注册委托引发了异常.配置无效.CacheUserRepository类型直接或间接取决于它自身.

我的代码:

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" };
    }
}      
Run Code Online (Sandbox Code Playgroud)

这是我的缓存存储库:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的作文根:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ven 9

发生的情况如下:您CacheUserRepository按服务类型注册了该类IUserRepository.这意味着每次有人请求IUserRepository(通过调用GetInstance<IUserRepository>()或通过要求IUserRepository构造函数参数),Simple Injector将为其提供新CacheUserRepository实例.

到目前为止这么好,但它CacheUserRepository本身包含一个构造函数的参数IUserRepository.这将导致Simple Injector为您CacheUserRepository提供新CacheUserRepository实例.当然,这个新实例再次提供了一个新CacheUserRepository实例.由于这会导致stackoverflow异常,Simple Injector会阻止这种情况并抛出您看到的异常.

CacheUserRepository其实是装饰师.Simple Injector支持处理装饰器.这是您的注册应如下所示:

container.Register<IUserRepository, UserRepository>();
container.RegisterDecorator<IUserRepository, CacheUserRepository>();
Run Code Online (Sandbox Code Playgroud)

RegisterDecorator方法特别注意循环依赖性,并确保Simple Injector不会追逐它的尾部.