Dependency injection 资源生命周期控制问题

Dependency injection 资源生命周期控制问题,dependency-injection,autofac,Dependency Injection,Autofac,我试图找到一种方法来管理独立于使用它的组件的资源的生命周期。下面的示例显示了我的方法。它还没有达到预期的效果,但它表明了我的意图 class GlobalService { static int instanceCounter = 0; public int instanceId = ++instanceCounter; public void DoWhatever() { } } class Consumer { private readonly Func&l

我试图找到一种方法来管理独立于使用它的组件的资源的生命周期。下面的示例显示了我的方法。它还没有达到预期的效果,但它表明了我的意图

class GlobalService
{
    static int instanceCounter = 0;
    public int instanceId = ++instanceCounter;
    public void DoWhatever() { }
}

class Consumer
{
    private readonly Func<Owned<GlobalService>> _globalServiceFactory;
    public Consumer(Func<Owned<GlobalService>> globalServiceFactory)
    {
        _globalServiceFactory = globalServiceFactory;
    }

    public void UseService()
    {
        using (var service = _globalServiceFactory())
        {
            service.Value.DoWhatever();
            Console.WriteLine("service.instanceId = {0}\n", service.Value.instanceId);
        }
    }
}

class Program
{
    static ILifetimeScope rootScope;
    static ILifetimeScope globalServiceScope;
    static ILifetimeScope consumerScope;

    static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<GlobalService>().InstancePerMatchingLifetimeScope("globalServiceScope");
        builder.RegisterType<Consumer>().InstancePerMatchingLifetimeScope("consumerScope");

        var container = builder.Build();
        this.rootScope = container.BeginLifetimeScope();
        this.globalServiceScope = rootScope.BeginLifetimeScope("globalServiceScope");
        this.consumerScope = globalServiceScope.BeginLifetimeScope("consumerScope");

        var consumer = consumerScope.Resolve<Consumer>();
        consumer.UseService(); // service.instanceId is 1
        ResetServiceScope();
        consumer.UseService(); // service.instanceId is 1, but I want it to be 2
    }

    static void ResetServiceScope()
    {
        globalServiceScope.Dispose();
        globalServiceScope = rootScope.BeginLifetimeScope("globalServiceScope");
    }
}
class-GlobalService
{
静态int instanceCounter=0;
公共int instanceId=++instanceCounter;
公共无效DoWhatever(){}
}
阶级消费者
{
私有只读功能(GlobalService Factory);
公共消费者(Func全球服务工厂)
{
_globalServiceFactory=globalServiceFactory;
}
公共服务
{
使用(var服务=_globalServiceFactory())
{
service.Value.DoWhatever();
WriteLine(“service.instanceId={0}\n”,service.Value.instanceId);
}
}
}
班级计划
{
静态髂腓肠镜根镜;
静态ILifetimeScope全球服务镜;
静态ILifetimeScope消费镜;
静态void Main(字符串[]参数)
{
var builder=new ContainerBuilder();
builder.RegisterType().InstancePerMatchingLifetimeScope(“globalServiceScope”);
builder.RegisterType().InstancePerMatchingLifetimeScope(“consumerScope”);
var container=builder.Build();
this.rootScope=container.BeginLifetimeScope();
this.globalServiceScope=rootScope.BeginLifetimeScope(“globalServiceScope”);
this.consumerScope=globalServiceScope.BeginLifetimeScope(“consumerScope”);
var consumer=consumerScope.Resolve();
consumer.UseService();//service.instanceId为1
重置服务范围();
consumer.UseService();//service.instanceId是1,但我希望它是2
}
静态void ResetServiceScope()
{
globalServiceScope.Dispose();
globalServiceScope=rootScope.BeginLifetimeScope(“globalServiceScope”);
}
}
我想实现
消费者
中的工厂始终返回当前活动的
全局服务
实例,其生存期在其他地方控制,以便
消费者
不需要知道有关如何重新加载
全局服务的任何信息


我不确定我是否真的误用了Autofac(或者一般的DI),因为我刚刚开始使用它(以及一般的DI)。不管我是否误用了它,我现在有点被困在这里,如果有人能给我指出正确的方向,我将不胜感激。

我很肯定你误用了生命周期望远镜。由于
consumerScope
是从
globalServiceScope
创建的,因此当您处置
globalServiceScope
时,您也在处置
consumerScope
。从技术上讲,从任一范围解析的任何服务都不应再被访问。例如,如果
Consumer
实现了
IDisposable
,则当您处置
globalServiceScope
时,它将被处置

我不确定你到底想完成什么,所以我不能建议一个更好的方法

编辑:Alexander指出,我不正确地认为内部容器是在外部容器被释放时被释放的,但这是因为一个已知的bug没有简单的修复,而不是因为它是有效的行为。如果有人修复了这个bug,上述用法就会中断

编辑2:我调整了你的代码,引入了一个
ReloadableSingleton
类,因为我认为这就是你想要实现的。我添加了一些Debug.Assert代码只是为了验证它是否有效。显然,你可以把这个拿出来。如果您使用
IGlobalService
接口,并注册一个将每个方法调用延迟到singleton的实现,您可以消除Consumer中的
Func
需求,但我不想编写所有这些代码,以防这偏离正轨。这有用吗

使用系统;
使用系统诊断;
使用Autofac;
使用Autofac.Builder;
名称空间演示
{
内部类GlobalService
{
私有静态int instanceCounter=0;
公共int instanceId=++instanceCounter;
公共无效DoWhatever(){}
}
内部类消费者
{
私有只读功能(GlobalService Factory);
公共消费者(Func全球服务工厂)
{
_globalServiceFactory=globalServiceFactory;
}
公共服务
{
var服务=_globalServiceFactory();
service.DoWhatever();
WriteLine(“service.instanceId={0}\n”,service.instanceId);
return service.instanceId;
}
}
内部课程计划
{
私有常量字符串ConsumerTag=“consumerScope”;
私有常量字符串GlobalServiceTag=“globalServiceScope”;
专用静态ILifetimeScope根镜;
专用静态ILifetimeScope全局服务镜;
专用静态ILifetimeScope消费示波器;
私有静态void Main()
{
var builder=new ContainerBuilder();
//根范围:
builder.RegisterReloadableSingleton();
//全球服务范围:
builder.RegisterType().InstancePerMatchingLifetimeScope(GlobalServiceTag);
builder.RegisterSingletonReloader().InstancePerMatchingLifetimeScope(GlobalServiceTag);
//消费者范围:
builder.RegisterReadableSingletonAccessor().InstancePerMatchingLifetimeScope(ConsumerTag);
builder.RegisterType().InstancePerMatchingLifetimeScope(ConsumerTag);
使用(var container=builder.Build())
使用(rootScope=container.BeginLifetimeScope())
{
重新加载GlobalService();
consumerScope=rootScope.BeginLifetimeScope(ConsumerTag);
var consumer=consumerScope.Resolve();
Assert(consumer.UseService()==1,“1”);
重新加载GlobalService();
Assert(consumer.UseService()==2,“2”);