简体   繁体   English

不使用Autofac命名空间的隐式作用域

[英]Implicit scope on resolve without using Autofac namespace

I am trying to figure out how to get a new lifetime scope each time I resolve an instance from the container. 我试图弄清楚每次我从容器解析实例时如何获得新的生存期范围。 I would like to do this without the depending component needing to know about Autofac. 我想要执行此操作而无需依赖组件来了解Autofac。

I'm creating a .NET Core server application (console app) which has a "master server" ( IMasterServer ) component and zero or more "session server" ( ISessionServer ) components. 我正在创建一个.NET Core服务器应用程序(控制台应用程序),它具有一个“主服务器”( IMasterServer )组件和零个或多个“会话服务器”( ISessionServer )组件。 Both the master and the session servers have their own IMessageBroker dependency. 主服务器和会话服务器都具有自己的IMessageBroker依赖性。 The master server will create a new session server whenever it gets a message from the message broker. 每当主服务器从消息代理获取消息时,它将创建一个新的会话服务器。

The catch is that each session server instance needs its own IMessageBroker , and I don't think I can use InstancePerDependency() because other sub-components of ISessionServer will also need to access the IMessageBroker so the message broker needs to be single instance within the scope of a session. 问题是每个会话服务器实例都需要自己的IMessageBroker ,并且我认为我不能使用InstancePerDependency()因为ISessionServer其他子组件也需要访问IMessageBroker因此消息代理必须是会话范围。 So my thinking is that when the master server spawns a new session, it should do so within a new lifetimescope, and I can register the IMessageBroker dependency using InstancePerLifetimeScope() . 所以我的想法是,当主服务器产生新会话时,它应该在新的生命周期范围内进行,并且我可以使用InstancePerLifetimeScope()注册IMessageBroker依赖项。

So, the question is, how can I inject an ISessionServer factory into IMasterServer such that each time that factory is called, a new lifetime scope is created for the resulting ISessionServer instance? 因此,问题是,如何将ISessionServer工厂注入IMasterServer ,以便每次调用该工厂时,都为生成的ISessionServer实例创建一个新的生存期作用域? And how can this be done such that none of the components need to know about Autofac? 怎样才能使所有组件都不需要了解Autofac?

These two SO questions both suggest using the Owned<T> relationship: 这两个SO问题都建议使用Owned<T>关系:

Can I create an implicit Lifetime scope within a factory? 我可以在工厂内创建隐式生命周期范围吗?

Is it possible to create a new scope whenever a component is resolved? 解析组件后是否可以创建新的作用域?

However, unless I'm missing something, that means that the component into which the dependency will be injected ( IMasterServer in my case) needs to know about Autofac, because its ctor signature must include the Owned<T> type. 然而,除非我失去了一些东西,这意味着到其中的依存度将(要注射的成分IMasterServer在我的情况)需要了解Autofac,因为它的构造函数的签名必须包括Owned<T>类型。

What I have so far: 到目前为止,我有:

using Autofac.Features.OwnedInstances;

class MasterServer : IMasterServer
{
    private IMessageBroker mMessageBroker;
    private Func<Owned<ISessionServer>> mSessionServerFactory;

    public Master(
        Func<string, IServerMessageBroker> messageBrokerFactory,
        Func<Owned<ISessionServer>> sessionServerFactory
    )
    {
        mMessageBroker = messageBrokerFactory("master");
        mSessionServerFactory = sessionServerFactory;
    }
}


class SessionServer : ISessionServer
{
    private IMessageBroker mMessageBroker;
    private string mId;

    public SessionServer(
        Func<string, IMessageBroker> messageBrokerFactory
    )
    {
        mId = Guid.NewGuid().ToString();
        mMessageBroker = messageBrokerFactory(mId);
    }
}

You can see that the MasterServer concrete class needs to use the Autofac.Features.OwnedInstances namespace in order to define the session factory using the Owned<T> relationship type. 您可以看到MasterServer具体类需要使用Autofac.Features.OwnedInstances命名空间,以便使用Owned<T>关系类型定义会话工厂。

How can I use Autofac to create a new lifetime scope each time ISessionServer is resolved through the factory injected into the MasterServer , without the components needing to know anything about the specific DI container in use? 每次通过ISessionServer通过注入到MasterServer的工厂来解析ISessionServer我如何使用Autofac创建新的生存期作用域,而组件无需了解所使用的特定DI容器的任何信息?

I always felt that letting Autofac-specific code slip onto factory classes is the less of two evils. 我一直觉得让特定于Autofac的代码放到工厂类上可以减少两个弊端。 So, if I was in you, I would just use the Owned<T> class, call it a day and move on. 因此,如果我在您里面,我将只使用Owned<T>类,将其命名为“ day”然后继续。 It's an excellent solution and keeps all the disposing of every component automagical as always with Autofac. 这是一个极好的解决方案,并且使Autofac像往常一样自动处理所有组件。

Just remember to call Dispose or your owned SessionServer when needed, or you will leak resources. 只需记住在需要时调用Dispose或您自己的SessionServer ,否则您将泄漏资源。

AFAICT the Autofac approach doesn't let you write 100% DI free code. AFAICT的Autofac方法不允许您编写100%无DI的代码。 So you need to reference it, someway, somewhere. 因此,您需要在某些地方引用它。

A single reference to include Owned<T> seems a pretty acceptable trade off. 包含Owned<T>单个引用似乎是可以接受的折衷方案。

Let me point out a problem in your design (or in the part you included): there is no simple way to link a ISessionServer into a disposable scope. 让我指出您的设计(或包含的零件)中的一个问题:没有简单的方法将ISessionServer链接到一次性作用域中。

Eg: you expose a factory class, and then the SessionServer is out on his own. 例如:您公开了一个工厂类,然后SessionServer自行退出。 Managing scopes in this way becomes hard. 以这种方式管理范围变得困难。

A cleaner approach is to use a Disposable into a using statement: 一种更干净的方法是在Disable语句中使用Disposable:

using (var sessionServer = sessionFactory.GetServer())
{
    // do something with sessionServer.
}

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

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