c# - 来自 Assembly 的 Autofac 寄存器类型
问题描述
我在我的解决方案中使用 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;
}
});
下面的代码片段是构建容器时调用的回调委托。核心库需要在热插拔扩展之前解析和初始化,因为大多数扩展都依赖于它们。
//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实际上将我带到了一个完全不同的类的构造函数——不同的类在执行程序集中——
解决方案
经过一段时间的真正挖掘,我将文件加载简化为:
var path = "C:\\rust server\\RustDedicated_Data\\Managed";
var coreFiles = Directory.GetFiles(path, "vmecore.*.dll");
var coreExtension = new List<Type>();
// Load each assembly into domain
foreach (var file in coreFiles)
{
var lAssembly = Assembly.LoadFile(file);
var assembly = Assembly.Load(lAssembly.FullName);
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.IsAssignableTo<IVmeExtension>())
.SingleInstance();
// Add all IVmeExtension types
coreExtension.AddRange(assembly.GetExportedTypes()
.Where(a => a.IsClass &&
!a.IsAbstract &&
a.Namespace != null &&
a.Namespace.Contains(@"VME") &&
typeof(IVmeExtension).IsAssignableFrom(a)));
}
我的原始版本不起作用的原因是,即使加载了文件程序集,它也没有加载到应用程序域中,所以当我注册一个类型时,它会得到一个哈希码——autofac 使用它——。当应用程序尝试解析类型时,它会将程序集加载到应用程序域中。此时,所有新加载的类型都有不同的哈希码——我认为这是正在发生的事情——导致我描述的错误。
奇怪的是,我提到的无效指针异常实际上是在激活第二个扩展并以正确的方式解决其依赖关系时产生的,其中一个打开了一个 tcp 套接字,该套接字具有错误输入的 ip 地址(uurghh co-workers ehh)
有时,更简单的代码是更好的代码:)
推荐阅读
- machine-learning - 将包添加到 Spacy 管道时出现错误
- node.js - EC2 冻结安装 NodeJS 包 NPM/Yarn - AWS
- javascript - 如何使用 Python 从按钮中抓取隐藏的超链接?
- python - Python随机方形运动不起作用
- matrix - 嗨,我是编程新手,如何执行此代码?
- rest - GET with body (json format), what to do with apostrophe?
- dynamic - SSIS 连接字符串不会在 OLE DB 源的子包中动态更改
- tensorflow - 为什么我的 ONNX 模型从 PyTorch 转换后输入为 0?
- node.js - 防止控制台输出中的数组换行符(Visual Studio Code;Node.js)
- ruby-on-rails - RoR Puma:启动请求重复太快