【发布时间】:2018-08-09 21:52:48
【问题描述】:
我在我的解决方案中使用 autofac 来解决不同项目之间的库依赖关系。这个想法是在某种意义上制作热插拔库,只有少数几个核心库是应用程序所依赖的,它们的前缀是"vmecore.*.dll"。必须在任何其他库之前向 autofac 注册。
任何其他以“vme.*.dll”为前缀的库都已加载,然后我寻找实现“IVmeExtension”的第一个类型——它定义了一个Initiate()方法——我注册,激活,最后初始化。
注册核心库的代码:
Directory.GetFiles(path, "vmecore.*.dll")
.Select(Assembly.LoadFile)
.ToList()
.ForEach(ass =>
{
//var validAss = Assembly.Load(ass.FullName);
builder.RegisterAssemblyTypes(ass)
.Where(t => t.IsAssignableTo<IVmeExtension>())
.SingleInstance();
//return;
// Iterate through all the types in the assembly
foreach (var type in ass.GetExportedTypes()
.Where(a => a.IsClass &&
!a.IsAbstract &&
a.Namespace != null &&
a.Namespace.Contains(@"VME")))
{
// Get the first type of IVmeExtension
if (!typeof(IVmeExtension).IsAssignableFrom(type)) continue;
//builder.RegisterType(type).SingleInstance();
coreExtension.Add(type);
break;
}
});
下面的 sn-p 是容器构建时调用的回调委托。核心库需要在热插拔扩展之前解析和初始化,因为大多数扩展都依赖于它们。
//Register a call back when container is built so we can resolve core extensions first
builder.RegisterBuildCallback(container =>
{
coreExtension.ForEach(ext =>
{
try
{
var inst = (IVmeExtension)container.Resolve(ext);
inst.Initiate();
Interface.LogInfo($"VME: Core extension '{inst.Name}'");
}
catch (Exception e)
{
// we log the error here.
throw;
}
});
});
解析的第二个扩展需要将前者注入构造函数——对于这个实验,我在构造函数中手动解析它以查看注册的服务——。问题出现在这里;我收到异常“请求的服务'..'尚未注册”但查看注册类型是文学那里。
我已经尝试过在这篇帖子https://github.com/autofac/Autofac/issues/593 上建议的解决方案,但是当我这样做时,我得到一个系统指针异常,并且它非常清楚,因为当进入实例(var inst = (IVmeExtension)container.Resolve(ext)) 的激活时,IDE 实际上正在带我到一个完全不同的类的构造函数 - 不同的类在执行程序集中 -
【问题讨论】:
-
那些扩展可能应该从构造函数初始化(如果有的话,需要它们的依赖项)——你有什么理由必须通过额外的初始化调用使它成为一个特殊情况?另外 -
RegisterAssemblyTypes确保它只是具体的类 - 所以不应该有理由检查抽象等。ToList也似乎是多余的。你能提供一个MVCE吗?