视觉工作室外接程序的依赖项注入
本文关键字:依赖 注入 程序 工作室 视觉 | 更新日期: 2023-09-27 18:32:02
我正在开发一个Visual Studio加载项,该加载项在您的项目中接受SQL查询,播放请求并为结果生成C#包装类。我想做一个最简单的依赖项注入,其中使用我的外接程序的项目提供了一个类,该类可以提供项目的数据库连接字符串等。
此接口在我的加载项中定义...
[Serializable]
public interface IDesignTimeQueryProcessing
{
public string ConnectionString { get; }
...
}
问题:如何定义和实例化具体实现,然后从加载项使用它?
进展?
上面的接口在加载项中定义。我在目标项目中创建了对外接程序的引用,编写了具体实现,并将此类的名称放在目标项目 web.config 中。现在,我需要从外接程序加载目标项目以使用我的具体类。
如果我使用 Assembly.Load()...
var userAssembly = Assembly.LoadFrom(GetAssemblyPath(userProject));
IQueryFirst_TargetProject iqftp = (IQueryFirst_TargetProject)Activator.CreateInstance(userAssembly.GetType(typeName.Value));
我可以成功加载我的类,但我锁定了目标程序集,无法再编译目标项目。
如果我创建临时应用程序域...
AppDomain ad = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(targetAssembly) });
byte[] assemblyBytes = File.ReadAllBytes(targetAssembly);
var userAssembly = ad.Load(assemblyBytes);
我在来电广告上收到未找到文件异常。Load(),即使我的 dll 的字节在内存中。
如果我使用 CreateInstanceFromAndUnwrap()...
AppDomain ad = AppDomain.CreateDomain("tmpDomain", null, new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(targetAssembly) });
IQueryFirst_TargetProject iqftp = (IQueryFirst_TargetProject)ad.CreateInstanceFromAndUnwrap(targetAssembly, typeName.Value);
我得到一个
无效投射异常。"无法将透明代理转换为类型 QueryFirst.IQueryFirst_TargetProject"
这让我觉得我很接近?为什么显式强制转换在 Assembly.Load() 中工作正常,但在新创建的 AppDomain 中加载同一程序集时失败?
我假设您的加载项将以某种方式触发以开始使用SQL查询。
我建议您在加载项中捆绑一个单独的.exe文件,并在其中进行处理。
原因如下:
- 就个人而言,我在AppDomain上遇到了很多问题,类似于您在文件锁定和临时域中遇到的头痛。 您可能会遇到的另一个问题是,一旦将程序集加载到 AppDomain 中,就无法卸载。 通过使用单独的进程(完成后会死亡),您不必担心问题。
- 根据要支持的项目类型,这些项目将具有依赖项。 如果您可以将独立.exe指向目录(即 bin 目录),则管理对依赖 dll 的引用将容易得多。
- 如果你挂接到Visual Studio的生成事件(
DTE.Events.BuildEvents.OnBuildBegin
),你可以终止你的进程并释放dll文件上的锁。 或者,您可以先让您的流程制作副本。 - 使用独立文件进行测试/调试要容易得多。 你不需要担心通过附加到Visual Studio(如何调试Vsix项目)来尝试调试。
您可以使用以下方法来启动/终止进程:
-
Process.Start
-
Process.Kill
我认为您可以通过 VSIX 包的引用剖析直接从 VSIX 添加项目引用控制台项目的输出。 因此,您可能需要执行一些自定义 MSBuild 才能将.exe包含在 VSIX 文件中。
包含它后,您可以找到.exe,因为它应该与执行 VSIX (Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location
) 位于同一路径中,我会将路径传递给加载的项目的 bin 目录。
顺便说一句,这不是依赖注入。 如果你想在VS扩展中使用DI,你可以使用任何你想要的框架,但我认为MEF是原生支持的。 就个人而言,我更喜欢Ninject。 在 Package
类中定义您的Kernel
,并使用它来加载您的顶级类。