繁体   English   中英

DryIoc:用两个接口注册装饰器,解析另一个接口时获取装饰器实例

[英]DryIoc: register decorator with two interfaces, retrieve the decorator instance when resolving the other interface

这是我试图解决的问题的稍微简化的描述:我有一个服务(例如存储库)实现了一个接口,我需要将其作为依赖项注入:

public class Service: IService {... }

我想添加一个装饰器,例如添加还实现另一个接口的缓存的装饰器:

public class CachingService: IService, IFlushable
{
  public CachingService(IService decoratee) { ... }

  public void Flush() { ... }
}

public interface IFlushable
{
  public void Flush();
}

通常,我只是使用Setup.DecoratorSetup.DecoratorWith将 CachingService 注册为 IService 的实现作为装饰器。 但在这种情况下,我有一个与 IFlushable 接口相关的额外要求。 将有几个不同的服务有自己的装饰器,它们都实现了装饰服务接口和 IFlushable。 我需要将所有 IFlushable 装饰器作为依赖项注入,以便能够根据请求刷新所有缓存。

public class CacheHandler
{
  public CacheHandler(IFlushable[] cache) { ... }

  public void FlushAllCaches() { ... }
}

问题在于此 CacheHandler 必须接收应用于服务类的相同装饰器实例。

我尝试了几种使用RegisterMapping的解决方案,并尝试将缓存的分辨率 scope 解析为其装饰服务,但我无法使其工作。 我收到容器无法解析装饰器的错误(这是有道理的),或者我需要自己注册装饰器,但在后一种情况下,CacheHandler 将收到一组新的 IFlushable 实例。

我越想越觉得我在这里试图实现的目标甚至可能无法使用 DI 容器。 我的意思是也许我以错误的方式解决了这个问题。 我的问题是我的方法是否有效和/或如何将所有已应用的 IFLushable 装饰器实例作为依赖项获取。

首先,我同意@Steven考虑反转控制并将IFlushable注入CachingService

其次,您可能会以不同的方式实现IService的装饰器——无需在CachingService中实现它:

    [Test]
    public void Answer()
    {
        var c = new Container();

        c.Register<IService, Service>(Reuse.Singleton);
        c.RegisterMany<CachingService>(Reuse.Singleton); // registers both CashingService and IFlushable with the same implementing instance
        c.RegisterDelegate<CachingService, IService>(cs => cs.GetDecoratedService(), setup: Setup.Decorator);

        var s = c.Resolve<IService>();
        Assert.IsNotNull(s);
        var cs = c.Resolve<CachingService>();
        Assert.IsTrue(cs.ServiceDecorated); // check the service indeed is decorated
        
        var f = c.Resolve<IFlushable>();
        Assert.AreSame(cs, f); // check that the flushable and caching service are the same instance
    }

    public interface IService { }

    public class Service : IService { }

    // no need to implement IService for the decorator, we may use its method instead
    public class CachingService : IFlushable
    {
        public readonly IService Service;
        public bool ServiceDecorated;

        public CachingService(IService service) => Service = service;

        public IService GetDecoratedService()
        {
            ServiceDecorated = true; // do something with decorated service
            return Service; 
        }

        public void Flush() { }
    }

    public interface IFlushable
    {
        public void Flush();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM