【问题标题】:Injecting factory using Autofac vs. delegate factories使用 Autofac 与委托工厂注入工厂
【发布时间】:2016-12-12 22:52:58
【问题描述】:

我是 Autofac 的新用户。

我有一个工厂需要根据工厂方法的输入创​​建不同的类,但只有一个需要创建的类有其他依赖项。

我找到了这个答案: Autofac Binding at Runtime

谁的解决方案效果很好。

但后来我开始阅读有关 Autofac 的委托工厂 (http://docs.autofac.org/en/latest/advanced/delegate-factories.html)... 现在我很困惑。

看来,如果您使用委托工厂,那么您实际上根本不需要编写工厂类?

这是我当前工厂类的片段:

public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
{
    private readonly IComponentContext autofacContainer;

    public ExternalUserInformationProviderFactory(IComponentContext autofacContainer)
    {
        this.autofacContainer = autofacContainer;
    }

    public IProvideExternalUserInformation GetExternalUserInformationProvider(string loginProvider)
    {
        switch (loginProvider)
        {
            case "Google":
                return autofacContainer.Resolve<GoogleExternalUserInformationProvider>();
            case "Twitter":
                return autofacContainer.Resolve<TwitterExternalUserInformationProvider>();
        }
        return null;
    }
}

在此示例中,TwitterExternalUserInformationProvider 在其构造函数中采用了依赖项:

public class TwitterExternalUserInformationProvider : IProvideExternalUserInformation
{
    private readonly ITwitterRepository twitterRepository;

    public TwitterExternalUserInformationProvider(ITwitterRepository twitterRepository)
    {
        this.twitterRepository = twitterRepository;
    }
}

而且 GoogleExternalUserInformationProvider 根本不需要构造函数参数。

这是我在 Startup.cs 中连接这个工厂的方式(我使用的是 asp.net core):

var containerBuilder = new ContainerBuilder();
containerBuilder.Register<IExternalUserInformationProviderFactory>(c => new ExternalUserInformationProviderFactory(c.Resolve<IComponentContext>()));
containerBuilder.RegisterType<TwitterExternalUserInformationProvider>();
containerBuilder.RegisterType<GoogleExternalUserInformationProvider>();

Autofac 足够聪明,可以为我解决 ITwitterRepository 依赖项,这真的很酷。

基于当前的实现,我是否可以使用委托工厂并完全摆脱 ExternalUserInformationProviderFactory?

我很好奇。

谢谢

【问题讨论】:

    标签: dependency-injection delegates autofac factory


    【解决方案1】:

    委托工厂不会在服务的两种实现之间进行选择,它只会根据其依赖关系创建一个组件。

    在您的情况下,您需要一个工厂。除了依赖IComponentContext,您的工厂还可以依赖IIndex&lt;String, IProvideExternalUserInformation&gt;,这可以避免范围& co的问题。

    您的ExternalUserInformationProviderFactory 可能如下所示:

    public class ExternalUserInformationProviderFactory : IExternalUserInformationProviderFactory
    {
        public ExternalUserInformationProviderFactory(IIndex<String, IProvideExternalUserInformation> providers)
        {
            this._providers = providers;
        }
    
        private readonly IIndex<String, IProvideExternalUserInformation> _providers; 
    
    
        public IProvideExternalUserInformation GetExternalUserInformationProvider(String loginProvider)
        {
            IProvideExternalUserInformation provider;
            if (!this._providers.TryGetValue(loginProvider, out provider))
            {
                throw new Exception("boom"); 
            }
            return provider; 
        }
    }
    

    和您的注册:

    builder.RegisterType<TwitterExternalUserInformationProvider>()
           .Named<IProvideExternalUserInformation>("twitter"); 
    builder.RegisterType<GoogleExternalUserInformationProvider>()
           .Named<IProvideExternalUserInformation>("google"); 
    builder.RegisterType<ExternalUserInformationProviderFactory>()
           .As<IExternalUserInformationProviderFactory>(); 
    

    【讨论】:

    • "这可能会避免与 scope & co 出现问题。"... "co." 是什么意思代表?另外,就我最初的解决方案而言,如何更改工厂以使用 IIndex 帮助/更好地让 Autfac 控制范围?
    • 此解决方案不需要 ExternalUserInformationProviderFactory 依赖于 IComponentContextOnly your composition root should know about the DI container
    • Chima,鉴于上述解决方案,由于 IIndex 被传递给工厂,工厂确实知道 Autofac ......所以我不太确定这个解决方案是否满足您提供给“只有你的作曲室应该知道 DI 容器"
    • @indiecodemonkey 你是对的,你的组件依赖于IIndex,你的组件依赖于Autofac。顺便说一句,这个工厂真的很小,你可以把它留在组合根级别:运行时级别的接口和组合根级别的实现。您还可以对其进行重构以使其具有通用性(即IFactory&lt;T&gt;
    • @indiecodemonkey 我不喜欢在不需要时依赖IComponentContextIComponentContext 很容易出错(通过创建子生命周期范围,通过访问组件注册表等)。顺便说一句,如果您查看KeyedServiceIndex 的源代码,它是IIndex 的默认实现,您将看到该组件依赖于IComponentContext :-)
    猜你喜欢
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多