[英]Autofac Container Update and Mock dependencies
As part of integration testing I would like to wrap a registered class with Autofac so that I can track what happens on that class and redirect the operations to the original implementation.作为集成测试的一部分,我想用 Autofac 包装一个已注册的类,以便我可以跟踪该类上发生的情况并将操作重定向到原始实现。
In the following example, I create a first container which the real app container and then create a spyContainer.在下面的示例中,我创建了第一个容器,即真正的应用程序容器,然后创建了一个 spyContainer。
The spyContainer should reuse the registeredInstance of NameRetriever
as well as the WorldLogger
but the WorldLogger
should be injected a HelloLoggerSpy
which itself should have been instanciated with the original IHelloLogger
.该spyContainer应该重用的registeredInstance
NameRetriever
还有WorldLogger
但WorldLogger
应注射一HelloLoggerSpy
本身应该被实例化与原来的IHelloLogger
。
public class NameRetriever
{
public string GetName()
{
return "linvi";
}
}
public interface IHelloLogger
{
void Hello();
}
public class HelloLogger : IHelloLogger
{
private readonly NameRetriever _nameRetriever;
public HelloLogger(NameRetriever nameRetriever)
{
_nameRetriever = nameRetriever;
}
public void Hello()
{
Console.WriteLine("Hello " + _nameRetriever.GetName());
}
}
public class WorldLogger
{
private readonly IHelloLogger _helloLogger;
public WorldLogger(IHelloLogger helloLogger)
{
_helloLogger = helloLogger;
}
public void World()
{
_helloLogger.Hello();
Console.WriteLine("Welcome in this world");
}
}
public class HelloLoggerSpy : IHelloLogger
{
private readonly IHelloLogger _sourceHelloLogger;
public bool Called { get; private set; }
public HelloLoggerSpy(IHelloLogger sourceHelloLogger)
{
_sourceHelloLogger = sourceHelloLogger;
}
public void Hello()
{
_sourceHelloLogger.Hello();
Called = true;
}
}
static void Main()
{
var containerBuilder = new ContainerBuilder();
// This is normal container creation
containerBuilder.RegisterInstance(new NameRetriever());
containerBuilder.RegisterType<HelloLogger>().As<IHelloLogger>();
containerBuilder.RegisterType<WorldLogger>();
var realContainer = containerBuilder.Build();
// This is something that would be invoked during tests
// to override the A behaviour
containerBuilder.Register<IHelloLogger>(context =>
{
var realA = context.Resolve<IHelloLogger>(); // recursive as IA is not yet reusing the previous one
var aSpy = new HelloLoggerSpy(realA);
return aSpy;
});
var spyContainer = containerBuilder.Build(); // cannot build twice
var b = spyContainer.Resolve<WorldLogger>();
b.World(); // should have called HelloLoggerSpy.Hello()
}
Anyone knows how to achieve this here and how will this be possible in the future?任何人都知道如何在这里实现这一目标以及未来如何实现?
It looks like HelloLoggerSpy
acts like the decorator pattern and Autofac has native support for such a pattern.看起来
HelloLoggerSpy
行为类似于装饰器模式,而Autofac对这种模式有本机支持。
Instead of your custom registration for HelloLoggerSpy
you can use :您可以使用以下
HelloLoggerSpy
代替HelloLoggerSpy
的自定义注册:
builder.RegisterDecorator<HelloLoggerSpy, IHelloLogger>();`
See Adapter and Decorators from the Autofac documentation for more information有关更多信息,请参阅 Autofac 文档中的适配器和装饰器
You can't build a container multiple time but you can create a childlifetime scope and register stuff on this new stuff.你不能多次构建一个容器,但你可以创建一个 childlifetime 范围并在这个新东西上注册东西。
using(var scope = realContainer.BeginLifetimeScope(b => {
b.RegisterDecorator<HelloLoggerSpy, IHelloLogger>();
}))
{
scope.Resolve<IHelloLogger>(); // => HelloLoggerSpy
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.