如何在 Autofac 装配体扫描和注册期间有选择地更改生存期范围

本文关键字:选择地 范围 生存期 注册 Autofac 扫描 | 更新日期: 2023-09-27 17:57:07

我有一个使用 AutoFac 从二进制文件夹中的程序集构建容器的类。这实质上是遍历 dll 并使用接口注册类:

    private static void RegisterAssembly(ContainerBuilder builder, string assemblyNamePattern)
    {
        // Get the path to the currently executing assembly. We will load dll's from here only.
        var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        if (String.IsNullOrWhiteSpace(path))
            return;
        // Get a list of all the assemblies in this folder
        var assembliesToRegister = (Directory.EnumerateFiles(path, assemblyNamePattern, SearchOption.TopDirectoryOnly)
                .Select(Assembly.LoadFrom)
                .ToArray());
        // Register the dll's
        builder.RegisterAssemblyTypes(assembliesToRegister).AsImplementedInterfaces();
    }

这工作正常,我可以创建我需要的类的实例。我遇到的问题是,其中有几个类是单例的(例如 Redis 缓存),因此需要注册为单例。在代码中,它们是使用 Lazy<> 定义的:

    private static readonly Lazy<CacheManager> _instance = new Lazy<CacheManager>(() => new CacheManager());
    public static ICacheManager Instance
    {
        get { return _instance.Value; }
    }

我想知道的是是否有某种方法可以告诉AutoFac某些类需要注册为单例。我猜我可以在构建容器后对其进行检查并将特定定义更改为单例,但是如果我可以让 Autofac 在注册时自动执行此操作,那会更可靠。

如何在 Autofac 装配体扫描和注册期间有选择地更改生存期范围

作为一种廉价的解决方案,当扫描DLL时,您可以排除一个或多个接口:

        // Register the dll's, except the singleton ones.
        builder.RegisterAssemblyTypes(assembliesToRegister)
                .AsImplementedInterfaces()
                .Except<IOne>()
                .Except<ITwo>();

这允许自动注册除单例之外的所有内容。接下来,注册单例:

AddSingletonInstance<IOne>(builder, assembliesToRegister, "OneType");
AddSingletonInstance<ITwo>(builder, assembliesToRegister, "TwoType");

这依赖于扫描之前创建的程序集列表的泛型方法:

    private static void AddSingletonInstance<T>(ContainerBuilder builder, Assembly[] assembliesToRegister, string typeName)
    {
        var singletonType = (from asm in assembliesToRegister
                        from tt in asm.DefinedTypes
                        where tt.Name == typeName
                        select tt).FirstOrDefault();
        if (singletonType != null)
            builder.RegisterType(singletonType).As<T>().SingleInstance().ExternallyOwned();
    }

这并不理想,但它有效。