DryIoc:用两个接口注册decorator,在解析另一个接口时检索decorator实例



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

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的实现注册为decorator。但在这种情况下,我有一个与IFlushable接口相关的额外需求。将有几个不同的服务具有自己的decorator,所有这些服务都实现了decorated服务接口和IFlushable。我需要注入所有IFlushable装饰器作为依赖项,以便能够根据请求刷新所有缓存。

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

问题是,这个CacheHandler必须接收应用于Service类的相同decorator实例。

我已经尝试了几种使用RegisterMapping的解决方案,并试图将缓存的解析范围扩大到它们装饰的服务,但我无法使其工作。要么我收到一个错误,即容器无法解析decorator(这是有道理的(,要么我需要自己注册decorator,但在后一种情况下,CacheHandler将接收一组新的IFlushable实例。

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

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

其次,您可能对IService的decorator有点不同——不需要在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();
}

最新更新