动态加载程序集组装解决问题
注:
这是我上一篇文章的延续: 动态调用程序集的复杂 API 问题
我正在编写一个 . Net windows 窗体应用程序在网络上运行并使用 SQL Server 来保存和提取数据。
我想提供一个迷你“插件”API,开发人员可以在其中构建自己的程序集并实现特定的接口(IDataManipulate)。然后,我的应用程序可以使用这些程序集来调用 IDataManipulate.Execute()。
我决定采用解决方案#3:
将 dll 字节以 byte[] 的形式保存到数据库中,并在每次用户启动我的应用程序时在本地 PC 上重新创建 dll。
这就是我正在做的事情:
- 我的应用程序提示用户上传实现我的 API 接口 (IDataManipulate)(“主”程序集)的 .Net 程序集,并将字节保存在数据库中。
- 然后,使用 Assembly.GetReferencedAssemblies 获取引用程序集的列表,并将其字节保存在数据库中(“引用”程序集),假设用户在同一文件夹中提供了实际文件。
问题:如何从 Assembly.GetReferencedAssemblies 列表中识别系统程序集并将其排除? - 当应用程序运行时,我从数据库获取主程序集的字节,使用 Assembly.Load(byte[]) 创建程序集并使用 CreateInstance(type),其中 type 是实现 IDataManipulate 的对象(因此我可以调用 IDataManipulate.执行())。
- 然后,我使用 AppDomain.AssemblyResolve 事件使用 Aseembly.Load(byte[]) 从数据库加载引用程序集的字节,
一切正常; dll 已加载,我可以调用 IDataManipulate.Execute(),但以下问题除外:
问题
当我从主程序集中调用 IDataManipulate.Execute() 时,出现如下错误:
“我无法从此程序集中加载类型 xxxx”。
无法加载的类型属于引用的程序集之一,而不是主程序集。
为什么会发生这种情况?
有什么建议吗?
Note:
This is a continuation of my previous post:
Complicated API issue with calling assemblies dynamically
I'm writing a .Net windows forms application that runs on a network and uses an SQL Server to save and pull data.
I want to offer a mini "plugin" API, where developers can build their own assemblies and implement a specific interface (IDataManipulate). These assemblies then can be used by my application to call IDataManipulate.Execute().
I've decided to go with solution #3 :
Save the dll bytes as byte[] to the database and recreate the dll at the local PC every time the user starts my application.
So this is what I'm doing:
- My application prompts the user to upload a .Net assembly that implements my API's interface (IDataManipulate) ("main" asseembly) and save the bytes in the database.
- Then, using Assembly.GetReferencedAssemblies I get a list of referenced assemblies and save their bytes in the database ("referenced" assemblies), assuming the user provided the actual files in the same folder.
Question: How can I recognize the system assemblies from the Assembly.GetReferencedAssemblies list and exclude them? - When the app runs, I get the bytes for the main assembly from the database, create the assembly with Assembly.Load(byte[]) and use CreateInstance(type) where type is the object that implements IDataManipulate (so I can call IDataManipulate.Execute()).
- Then I use the AppDomain.AssemblyResolve event to load the bytes of the references assemblies from the database using Aseembly.Load(byte[])
Everything works; the dlls are loaded and I can call IDataManipulate.Execute() except for this problem:
Problem
When I call IDataManipulate.Execute() from the main assembly, I get an error such as:
"I can't load type xxxx from this assembly".
The type that can't be loaded belongs to one of the referenced assemblies not the main one.
Why this is happening?
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要回答您的第一个问题,您可以检查引用的程序集的位置,并且仅当它位于同一文件夹中时才将其添加到数据库中。
To answer your first question, you can check the referenced assemblies' Location, and only add it to the database if it's in the same folder.
有点晚了,但您还可以检查程序集的 PublicKeyToken。我相信 .net 存在三种令牌。您可以通过查看 Windows Framework 文件夹来找到它们。这样,如果需要,您可以将程序集包含在其他文件夹中。
也就是说,我可能会要求开发人员将它们也放在同一个文件夹中。如果他们决定包含大型第三方库,例如 Infragistics 等。这样,他们必须在导入之前明确将程序集移动到文件夹中,使他们知道自己在做什么。
A bit late, but you can also check the PublicKeyToken of the assembly. Three tokens exist for .net, I believe. You can find them by looking in the windows framework folder. This way, you can include assemblies in other folders if you need to.
That said, I would probably require the developer to have them in the same folder as well. In case they decide to include large 3rd party libraries like Infragistics or whatnot. That way they explicitly have to move the assemblies to a folder before importing, making them aware of what they are doing.