为什么即使服务已注册,Autofac解析也会失败?

时间:2017-08-14 12:29:53

标签: c# autofac

当我调用Autofac的.Resolve方法时,我得到一个异常,说明我的组件尚未注册,但我不确定原因。

错误:

  

抛出异常:   'Autofac.Core.Registration.ComponentNotRegisteredException'中   Autofac.dll其他信息:请求的服务   'Nt.Bot.Sdi.Secure.SdiApiAccess.Login.ISdiLoginApi'尚未   注册。要避免此异常,请将组件注册到   提供服务,检查服务注册使用   IsRegistered(),或使用ResolveOptional()方法来解析   可选的依赖。

我按如下方式注册我的服务:

public void Configure(ContainerBuilder diContainer)
{
    diContainer.RegisterType<SdiLoginApi>().As<ISdiLoginApi>();
}

上面的configure方法在我的global.asax.cs中调用。请注意,NtDialogContext.DiContainer是一个静态属性:

        var containerBuilder = new ContainerBuilder();
        new BotDependencyInjectionConfig().Configure(containerBuilder);
        NtDialogContext.DiContainer = containerBuilder.Build();

然后我尝试按如下方式加载服务。这是我得到错误的地方(我也尝试了Resolve的'通用'版本):

using (var containerScope = NtDialogContext.DiContainer.BeginLifetimeScope())
{
    var loginApi = (ISdiLoginApi)containerScope.Resolve(typeof(ISdiLoginApi));
}

如果我在调用.Resolve之前使用调试器检查containerScope,我看到我的组件在containerScope.ComponentRegistry.Registrations中:

  

{Activator = SdiLoginApi(ReflectionActivator),Services =   [Nt.Bot.Sdi.Secure.SdiApiAccess.Login.ISdiLoginApi],终身=   Autofac.Core.Lifetime.CurrentScopeLifetime,Sharing = None,Ownership   = OwnedByLifetimeScope}

也许我误解了一些关于Autofac的事情?为什么我在尝试解决时遇到错误?

我正在使用Autofac v4.1.1,它是Bot Builder v3.5的依赖项。

1 个答案:

答案 0 :(得分:0)

这里的问题根本与Autofac无关。如果有人遇到同样的问题,我会发布答案。

我们使用MEF(Managed Extensibility Framework)加载“插件”程序集。作为这个加载过程的一部分,我们有代码迭代文件夹中的DLL并将它们加载到AppDomain中。

public static IEnumerable<Assembly> GetClientAssembliesRelativeToAssembly(Assembly asm, string subPath = null, string wildcard = "Sdi*.dll")
{
    var path = subPath != null
        ? Path.Combine(Path.GetDirectoryName(asm.CodeBase.Substring(8)), subPath)
        : Path.GetDirectoryName(asm.CodeBase.Substring(8));

    foreach (var dll in Directory.GetFiles(path, wildcard))
    {
        yield return Assembly.LoadFile(dll);
    }
}

上面的问题是我们使用“LoadFile”而不是“LoadFrom”。当我们使用LoadFile时,程序集将直接从您指定的位置加载。但是这会导致DLL的一个版本驻留在/ bin /中而另一个版本驻留在/ Temporary ASP.NET文件/文件夹中。

然后我们遇到了Autofac将一种类型与另一种类型(ISdiLoginApi与ISdiLoginApi)进行比较的情况。它们应该是相同的,但不是因为一个程序集是由MEF(和我们的“LoadFile”调用)加载而另一个是直接引用驻留在/ Temporary ASP.NET文件/中。所以ISdiLoginApi!= ISdiLoginApi和AutoFac.Resolve()失败。

所以解决方案是在我们的程序集加载代码中使用LoadFrom()。这样,所有程序集都从同一个地方加载,Autofac可以正常工作。