【问题标题】:Autofac scope configuration for multi-project solution多项目解决方案的 Autofac 范围配置
【发布时间】:2017-12-19 09:49:15
【问题描述】:

我有一个 ASP.NET Web 应用程序,到目前为止,它一直在使用 Autofac 配置类,它为应用程序中的服务指定了 InstancePerRequest()

从那时起,我在同一个解决方案中创建了一个新的控制台应用程序,它将负责运行自动化的作业流程。由于我不能为我的控制台应用程序使用 InstancePerRequest 配置,因此我需要更改我的配置。理想情况下,我不想将所有配置复制并粘贴到我的 JobRunner 应用程序中,并在那里使用“InstancePerLifetimeScope()”配置。

有没有更好的解决方案,我可以在很大程度上使用相同的配置来为两个项目提供服务?也许有一种方法可以覆盖我的 Job Runner 应用程序的配置,但不必为每个服务指定范围的更改?

【问题讨论】:

  • 您需要在您的工作运行器中使用示波器吗?
  • 我不确定,是吗?我想做的就是每当我在此应用程序中执行作业时能够解析我的服务,并在作业完成时终止。我的困难在于知道如何设置我的配置,以便它既适合我的 Web 应用程序,也适合作业运行器。
  • InstancePerLifetimeScope() 可能对两者都足够了,因为InstancePerRequest() 只是一个特定的生命周期范围,如果没有生命周期范围,它应该使用根范围。
  • 谢谢约翰。你能想到任何不满足的场景吗?

标签: c# asp.net-mvc dependency-injection autofac autofac-configuration


【解决方案1】:

虽然InstancePerLifetimeScopeInstancePerRequest 经常有相同的行为,但他们肯定有不同的意图。我会避免使用InstancePerLifetimeScope 作为替代品,因为它很容易产生意想不到的副作用。例如,如果您有一项服务,您原本打算只在 Web 请求期间存在,但突然之间它在您的应用程序期间存在(因为它无意中从根范围解析)。

这种影响在你的工作运行器中会更糟,特别是如果你没有创建自己的生命周期范围 - 在这种情况下,所有东西都将存在于根范围中,这意味着一个工作将与所有其他依赖它的作业共享服务实例。

在幕后,InstancePerRequest() 实际上只是使用众所周知的生命周期标签(您可以从 MatchingScopeLifetimeTags.RequestLifetimeScopeTag 获得)委托给 InstancePerMatchingLifetimeScope()。所以,你可以实现你所要求的一种方法是你可以切断中间人......例如,你可以更改你的 Autofac 模块以将生命周期范围标记作为构造函数参数:

internal class MyModule : Module
{
    private string _lifetimeScopeTag;

    public MyModule(string lifetimeScopeTag)
    {
        _lifetimeScopeTag = lifetimeScopeTag;
    }

    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes()
            // equivalent to: .InstancePerRequest()
            .InstancePerMatchingLifetimeScope(_lifetimeScopeTag);
    }    
}

现在,当您从 Web 构建容器时,您需要提供众所周知的生命周期范围标记:

internal static class WebIoC
{
    public static IContainer BuildContainer()
    {
        var lifetimeScopeTag = MatchingScopeLifetimeTags.RequestLifetimeScopeTag;

        var builder = new ContainerBuilder();
        builder.RegisterModule(new MyModule(lifetimeScopeTag));

        return builder.Build();
    }
}

对于您的工作执行者,您现在可以使用自己的生命周期范围标签来模仿这种行为!

internal static class JobRunnerIoC
{    
    public const string LifetimeScopeTag = "I_Love_Lamp";

    public static IContainer BuildContainer()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule(new MyModule(LifetimeScopeTag));

        // Don't forget to register your jobs!
        builder.RegisterType<SomeJob>().AsSelf().As<IJob>();
        builder.RegisterType<SomeOtherJob>().AsSelf().As<IJob>();

        return builder.Build();
    }
}

(我在这里假设您的每个作业都实现了一个接口,假设它看起来像这样):

public interface IJob
{
    Task Run();
}

现在你只需要在它们自己的生命周期范围内运行作业,使用你刚刚制作的标签,例如:

public class JobRunner
{
    public static void Main(string[] args)
    {
        var container = JobRunnerIoC.BuildContainer();

        // Find out all types that are registered as an IJob
        var jobTypes = container.ComponentRegistry.Registrations
            .Where(registration => typeof(IJob).IsAssignableFrom(registration.Activator.LimitType))
            .Select(registration => registration.Activator.LimitType)
            .ToArray();

        // Run each job in its own lifetime scope
        var jobTasks = jobTypes
            .Select(async jobType => 
            {
                using (var scope = container.BeginLifetimeScope(JobRunnerIoC.LifetimeScopeTag))
                {
                    var job = scope.Resolve(jobType) as IJob;
                    await job.Run();
                }
            });

        await Task.WhenAll(jobTasks);
    }
}

【讨论】:

  • 谢谢。目前我的所有类型都注册了为每个类型单独指定的范围,例如“builder.RegistertType().As().InstancePerLifetimeScope”。如果我调用“builder.RegisterAssemblyTypes().InstancePerMatchingLifetimeScope(lifetimeScope)”,这将消除为每个类型注册指定范围的需要吗?
  • 是的;但它也会注册 all 程序集类型。通常你会过滤到只在你的容器中注册你想要的类型;类似:builder.RegisterAssemblyTypes().Where(type =&gt; typeof(IJob).IsAssignableFrom(type)).InstancePerMatchingLifetimeScope(lifetimeScope)
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 2011-07-06
  • 2012-10-25
相关资源
最近更新 更多