存在Autofac注册,但servicelocator抛出ComponentNotRegisteredException

问题描述 投票:0回答:2

这里有一些示例代码

public void RegisterDependencies()
        {
            var builder = new ContainerBuilder();

            ConfigureModules(builder);
            ConfigureProfiles(builder);

            var container = builder.Build();

            ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));
        }

protected virtual void ConfigureModules(ContainerBuilder builder)
        {
            var assemblies = GetAssemblies();
            {
                builder.RegisterAssemblyModules(assemblies);
            }
        }

        protected virtual void ConfigureProfiles(ContainerBuilder builder)
        {
            var profiles = GetTypes<Profile>();

            builder.RegisterInstance(new MapperConfiguration(cfg => cfg.AddMaps(profiles)).CreateMapper())
                .As<IMapper>();
        }

GetAssemblies()方法加载并返回应用程序引用的程序集数组。所有模块都已注册并显示在servicelocator中。但是,当尝试使用以下代码解析接口时,出现ComponentNotRegisteredException:

_dlMembershipParserService =
                ServiceLocator.Current.GetInstance<IDLMembershipParserService>();

这里是其中一个模块的示例:

public class ServiceModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<DLMembershipParserService>().As<IDLMembershipParserService>();
            builder.RegisterType<DLMembershipExporterService>().As<IDLMembershipExporterService>();
        }
    }

有人有什么想法吗?程序集已加载,每个要加载的dll只有一个程序集。

我也尝试了以下代码,但结果相同:

protected virtual void ConfigureModules(ContainerBuilder builder)
        {
            var modules = GetTypes<IModule>().Select(m => (IModule)Activator.CreateInstance(m));

            foreach (var module in modules)
            {
                builder.RegisterModule(module);
            }
        }

但是唯一有效的是对模块的引用,就像这样:

builder.RegisterModule<ServiceModule>();

但是这不是我想要的。我需要能够添加模块并使它们被应用程序发现。

我感谢对此有任何见识。

谢谢

exception autofac registration
2个回答
0
投票

GetAssemblies()方法加载并返回该应用程序引用的程序集数组。

您是调用AppDomain.CurrentDomain.GetAssemblies()还是将程序集动态加载到您的应用程序中?如果是,请在调用DLMembershipParserService时检查包含GetAssemblies()及其相关类型的程序集是否已加载。

请注意,并非所有referenced程序集都在应用程序启动时加载。组件在首次使用时加载。如果您在代码中引用该模块,则可能是该原因。

如果需要强制加载所有引用的程序集,则必须使用Assembly.GetReferencedAssemblies方法来查找所有引用的程序集并将它们加载到您的应用程序中。

https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.getreferencedassemblies?view=netcore-3.1


0
投票

因此,我从.NET Core的角度发现了我需要做的事情,以便从.NET Core动态发现和加载程序集。

需要一个nuget包来加载.NET Core程序集,以便可以在运行时解析所有已注册的类型。程序包称为System.Runtime.Loader。

一旦安装,我便能够根据类型信息成功发现程序集,然后在运行时加载,注册和解析类型。

这里有一些示例代码:

public override Type[] GetTypes<T>()
{
    var assemblyPath = _assemblyHelper.GetEntryAssemblyLocation();
    var path = _pathHelper.GetDirectoryName(assemblyPath);

    var files = _fileHelper.GetFiles(path, "Tss.DLMembership.*.dll");

    return files.SelectMany(file => _assemblyHelper.LoadFile(file).GetTypes()
        .Where(t => typeof(T).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract))
    .ToArray();
}

public class AssemblyHelper : IAssemblyHelper
{
    public string GetEntryAssemblyLocation()
    {
        return AppContext.BaseDirectory;
    }

    public Assembly LoadFile(string fileName)
    {
        return AssemblyLoadContext.Default.LoadFromAssemblyPath(fileName);
    }
}

这解决了我在加载程序集和注册类型后解决注册类型的问题。

© www.soinside.com 2019 - 2024. All rights reserved.